clang-format everything
This commit is contained in:
@@ -6,8 +6,6 @@ using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
// Note: This order matches the order that the cards are defined in the original
|
||||
// code. This is relevant for consistency of results when choosing a random card
|
||||
// (for God Whim).
|
||||
@@ -24,81 +22,81 @@ const vector<uint16_t> ALL_ASSIST_CARD_IDS = {
|
||||
|
||||
AssistEffect assist_effect_number_for_card_id(uint16_t card_id) {
|
||||
static const unordered_map<uint16_t, AssistEffect> card_id_to_effect({
|
||||
{0x00F5, /* 0x0001 */ AssistEffect::DICE_HALF},
|
||||
{0x00F6, /* 0x0002 */ AssistEffect::DICE_PLUS_1},
|
||||
{0x00F7, /* 0x0003 */ AssistEffect::DICE_FEVER},
|
||||
{0x00F8, /* 0x0004 */ AssistEffect::CARD_RETURN},
|
||||
{0x00F9, /* 0x0005 */ AssistEffect::LAND_PRICE},
|
||||
{0x00FA, /* 0x0006 */ AssistEffect::POWERLESS_RAIN},
|
||||
{0x00FB, /* 0x0007 */ AssistEffect::BRAVE_WIND},
|
||||
{0x00FC, /* 0x0008 */ AssistEffect::SILENT_COLOSSEUM},
|
||||
{0x00FD, /* 0x0009 */ AssistEffect::RESISTANCE},
|
||||
{0x00FE, /* 0x000A */ AssistEffect::INDEPENDENT},
|
||||
{0x00FF, /* 0x000B */ AssistEffect::ASSISTLESS},
|
||||
{0x0100, /* 0x000C */ AssistEffect::ATK_DICE_2},
|
||||
{0x0101, /* 0x000D */ AssistEffect::DEFLATION},
|
||||
{0x0102, /* 0x000E */ AssistEffect::INFLATION},
|
||||
{0x0103, /* 0x000F */ AssistEffect::EXCHANGE},
|
||||
{0x0104, /* 0x0010 */ AssistEffect::INFLUENCE},
|
||||
{0x0105, /* 0x0011 */ AssistEffect::SKIP_SET},
|
||||
{0x0106, /* 0x0012 */ AssistEffect::SKIP_MOVE},
|
||||
{0x0121, /* 0x0013 */ AssistEffect::SKIP_ACT},
|
||||
{0x0137, /* 0x0014 */ AssistEffect::SKIP_DRAW},
|
||||
{0x0107, /* 0x0015 */ AssistEffect::FLY},
|
||||
{0x0108, /* 0x0016 */ AssistEffect::NECROMANCER},
|
||||
{0x0109, /* 0x0017 */ AssistEffect::PERMISSION},
|
||||
{0x010A, /* 0x0018 */ AssistEffect::SHUFFLE_ALL},
|
||||
{0x010B, /* 0x0019 */ AssistEffect::LEGACY},
|
||||
{0x010C, /* 0x001A */ AssistEffect::ASSIST_REVERSE},
|
||||
{0x010D, /* 0x001B */ AssistEffect::STAMINA},
|
||||
{0x010E, /* 0x001C */ AssistEffect::AP_ABSORPTION},
|
||||
{0x010F, /* 0x001D */ AssistEffect::HEAVY_FOG},
|
||||
{0x0125, /* 0x001E */ AssistEffect::TRASH_1},
|
||||
{0x0126, /* 0x001F */ AssistEffect::EMPTY_HAND},
|
||||
{0x0127, /* 0x0020 */ AssistEffect::HITMAN},
|
||||
{0x0128, /* 0x0021 */ AssistEffect::ASSIST_TRASH},
|
||||
{0x0129, /* 0x0022 */ AssistEffect::SHUFFLE_GROUP},
|
||||
{0x012A, /* 0x0023 */ AssistEffect::ASSIST_VANISH},
|
||||
{0x012B, /* 0x0024 */ AssistEffect::CHARITY},
|
||||
{0x012C, /* 0x0025 */ AssistEffect::INHERITANCE},
|
||||
{0x012D, /* 0x0026 */ AssistEffect::FIX},
|
||||
{0x012E, /* 0x0027 */ AssistEffect::MUSCULAR},
|
||||
{0x012F, /* 0x0028 */ AssistEffect::CHANGE_BODY},
|
||||
{0x0130, /* 0x0029 */ AssistEffect::GOD_WHIM},
|
||||
{0x0131, /* 0x002A */ AssistEffect::GOLD_RUSH},
|
||||
{0x0132, /* 0x002B */ AssistEffect::ASSIST_RETURN},
|
||||
{0x0133, /* 0x002C */ AssistEffect::REQUIEM},
|
||||
{0x0134, /* 0x002D */ AssistEffect::RANSOM},
|
||||
{0x0135, /* 0x002E */ AssistEffect::SIMPLE},
|
||||
{0x0136, /* 0x002F */ AssistEffect::SLOW_TIME},
|
||||
{0x023F, /* 0x0030 */ AssistEffect::QUICK_TIME},
|
||||
{0x0138, /* 0x0031 */ AssistEffect::TERRITORY},
|
||||
{0x0139, /* 0x0032 */ AssistEffect::OLD_TYPE},
|
||||
{0x013A, /* 0x0033 */ AssistEffect::FLATLAND},
|
||||
{0x013B, /* 0x0034 */ AssistEffect::IMMORTALITY},
|
||||
{0x013C, /* 0x0035 */ AssistEffect::SNAIL_PACE},
|
||||
{0x013D, /* 0x0036 */ AssistEffect::TECH_FIELD},
|
||||
{0x013E, /* 0x0037 */ AssistEffect::FOREST_RAIN},
|
||||
{0x013F, /* 0x0038 */ AssistEffect::CAVE_WIND},
|
||||
{0x0140, /* 0x0039 */ AssistEffect::MINE_BRIGHTNESS},
|
||||
{0x0141, /* 0x003A */ AssistEffect::RUIN_DARKNESS},
|
||||
{0x0142, /* 0x003B */ AssistEffect::SABER_DANCE},
|
||||
{0x0143, /* 0x003C */ AssistEffect::BULLET_STORM},
|
||||
{0x0144, /* 0x003D */ AssistEffect::CANE_PALACE},
|
||||
{0x0145, /* 0x003E */ AssistEffect::GIANT_GARDEN},
|
||||
{0x0146, /* 0x003F */ AssistEffect::MARCH_OF_THE_MEEK},
|
||||
{0x0148, /* 0x0040 */ AssistEffect::SUPPORT},
|
||||
{0x014A, /* 0x0041 */ AssistEffect::RICH},
|
||||
{0x014B, /* 0x0042 */ AssistEffect::REVERSE_CARD},
|
||||
{0x014C, /* 0x0043 */ AssistEffect::VENGEANCE},
|
||||
{0x014D, /* 0x0044 */ AssistEffect::SQUEEZE},
|
||||
{0x014E, /* 0x0045 */ AssistEffect::HOMESICK},
|
||||
{0x0240, /* 0x0046 */ AssistEffect::BOMB},
|
||||
{0x0241, /* 0x0047 */ AssistEffect::SKIP_TURN},
|
||||
{0x0242, /* 0x0048 */ AssistEffect::BATTLE_ROYALE},
|
||||
{0x0018, /* 0x0049 */ AssistEffect::DICE_FEVER_PLUS},
|
||||
{0x0019, /* 0x004A */ AssistEffect::RICH_PLUS},
|
||||
{0x001A, /* 0x004B */ AssistEffect::CHARITY_PLUS},
|
||||
{0x00F5, /* 0x0001 */ AssistEffect::DICE_HALF},
|
||||
{0x00F6, /* 0x0002 */ AssistEffect::DICE_PLUS_1},
|
||||
{0x00F7, /* 0x0003 */ AssistEffect::DICE_FEVER},
|
||||
{0x00F8, /* 0x0004 */ AssistEffect::CARD_RETURN},
|
||||
{0x00F9, /* 0x0005 */ AssistEffect::LAND_PRICE},
|
||||
{0x00FA, /* 0x0006 */ AssistEffect::POWERLESS_RAIN},
|
||||
{0x00FB, /* 0x0007 */ AssistEffect::BRAVE_WIND},
|
||||
{0x00FC, /* 0x0008 */ AssistEffect::SILENT_COLOSSEUM},
|
||||
{0x00FD, /* 0x0009 */ AssistEffect::RESISTANCE},
|
||||
{0x00FE, /* 0x000A */ AssistEffect::INDEPENDENT},
|
||||
{0x00FF, /* 0x000B */ AssistEffect::ASSISTLESS},
|
||||
{0x0100, /* 0x000C */ AssistEffect::ATK_DICE_2},
|
||||
{0x0101, /* 0x000D */ AssistEffect::DEFLATION},
|
||||
{0x0102, /* 0x000E */ AssistEffect::INFLATION},
|
||||
{0x0103, /* 0x000F */ AssistEffect::EXCHANGE},
|
||||
{0x0104, /* 0x0010 */ AssistEffect::INFLUENCE},
|
||||
{0x0105, /* 0x0011 */ AssistEffect::SKIP_SET},
|
||||
{0x0106, /* 0x0012 */ AssistEffect::SKIP_MOVE},
|
||||
{0x0121, /* 0x0013 */ AssistEffect::SKIP_ACT},
|
||||
{0x0137, /* 0x0014 */ AssistEffect::SKIP_DRAW},
|
||||
{0x0107, /* 0x0015 */ AssistEffect::FLY},
|
||||
{0x0108, /* 0x0016 */ AssistEffect::NECROMANCER},
|
||||
{0x0109, /* 0x0017 */ AssistEffect::PERMISSION},
|
||||
{0x010A, /* 0x0018 */ AssistEffect::SHUFFLE_ALL},
|
||||
{0x010B, /* 0x0019 */ AssistEffect::LEGACY},
|
||||
{0x010C, /* 0x001A */ AssistEffect::ASSIST_REVERSE},
|
||||
{0x010D, /* 0x001B */ AssistEffect::STAMINA},
|
||||
{0x010E, /* 0x001C */ AssistEffect::AP_ABSORPTION},
|
||||
{0x010F, /* 0x001D */ AssistEffect::HEAVY_FOG},
|
||||
{0x0125, /* 0x001E */ AssistEffect::TRASH_1},
|
||||
{0x0126, /* 0x001F */ AssistEffect::EMPTY_HAND},
|
||||
{0x0127, /* 0x0020 */ AssistEffect::HITMAN},
|
||||
{0x0128, /* 0x0021 */ AssistEffect::ASSIST_TRASH},
|
||||
{0x0129, /* 0x0022 */ AssistEffect::SHUFFLE_GROUP},
|
||||
{0x012A, /* 0x0023 */ AssistEffect::ASSIST_VANISH},
|
||||
{0x012B, /* 0x0024 */ AssistEffect::CHARITY},
|
||||
{0x012C, /* 0x0025 */ AssistEffect::INHERITANCE},
|
||||
{0x012D, /* 0x0026 */ AssistEffect::FIX},
|
||||
{0x012E, /* 0x0027 */ AssistEffect::MUSCULAR},
|
||||
{0x012F, /* 0x0028 */ AssistEffect::CHANGE_BODY},
|
||||
{0x0130, /* 0x0029 */ AssistEffect::GOD_WHIM},
|
||||
{0x0131, /* 0x002A */ AssistEffect::GOLD_RUSH},
|
||||
{0x0132, /* 0x002B */ AssistEffect::ASSIST_RETURN},
|
||||
{0x0133, /* 0x002C */ AssistEffect::REQUIEM},
|
||||
{0x0134, /* 0x002D */ AssistEffect::RANSOM},
|
||||
{0x0135, /* 0x002E */ AssistEffect::SIMPLE},
|
||||
{0x0136, /* 0x002F */ AssistEffect::SLOW_TIME},
|
||||
{0x023F, /* 0x0030 */ AssistEffect::QUICK_TIME},
|
||||
{0x0138, /* 0x0031 */ AssistEffect::TERRITORY},
|
||||
{0x0139, /* 0x0032 */ AssistEffect::OLD_TYPE},
|
||||
{0x013A, /* 0x0033 */ AssistEffect::FLATLAND},
|
||||
{0x013B, /* 0x0034 */ AssistEffect::IMMORTALITY},
|
||||
{0x013C, /* 0x0035 */ AssistEffect::SNAIL_PACE},
|
||||
{0x013D, /* 0x0036 */ AssistEffect::TECH_FIELD},
|
||||
{0x013E, /* 0x0037 */ AssistEffect::FOREST_RAIN},
|
||||
{0x013F, /* 0x0038 */ AssistEffect::CAVE_WIND},
|
||||
{0x0140, /* 0x0039 */ AssistEffect::MINE_BRIGHTNESS},
|
||||
{0x0141, /* 0x003A */ AssistEffect::RUIN_DARKNESS},
|
||||
{0x0142, /* 0x003B */ AssistEffect::SABER_DANCE},
|
||||
{0x0143, /* 0x003C */ AssistEffect::BULLET_STORM},
|
||||
{0x0144, /* 0x003D */ AssistEffect::CANE_PALACE},
|
||||
{0x0145, /* 0x003E */ AssistEffect::GIANT_GARDEN},
|
||||
{0x0146, /* 0x003F */ AssistEffect::MARCH_OF_THE_MEEK},
|
||||
{0x0148, /* 0x0040 */ AssistEffect::SUPPORT},
|
||||
{0x014A, /* 0x0041 */ AssistEffect::RICH},
|
||||
{0x014B, /* 0x0042 */ AssistEffect::REVERSE_CARD},
|
||||
{0x014C, /* 0x0043 */ AssistEffect::VENGEANCE},
|
||||
{0x014D, /* 0x0044 */ AssistEffect::SQUEEZE},
|
||||
{0x014E, /* 0x0045 */ AssistEffect::HOMESICK},
|
||||
{0x0240, /* 0x0046 */ AssistEffect::BOMB},
|
||||
{0x0241, /* 0x0047 */ AssistEffect::SKIP_TURN},
|
||||
{0x0242, /* 0x0048 */ AssistEffect::BATTLE_ROYALE},
|
||||
{0x0018, /* 0x0049 */ AssistEffect::DICE_FEVER_PLUS},
|
||||
{0x0019, /* 0x004A */ AssistEffect::RICH_PLUS},
|
||||
{0x001A, /* 0x004B */ AssistEffect::CHARITY_PLUS},
|
||||
});
|
||||
try {
|
||||
return card_id_to_effect.at(card_id);
|
||||
@@ -107,15 +105,13 @@ AssistEffect assist_effect_number_for_card_id(uint16_t card_id) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
AssistServer::AssistServer(shared_ptr<Server> server)
|
||||
: w_server(server),
|
||||
assist_effects(AssistEffect::NONE),
|
||||
num_assist_cards_set(0),
|
||||
client_ids_with_assists(0xFF),
|
||||
active_assist_effects(AssistEffect::NONE),
|
||||
num_active_assists(0) { }
|
||||
: w_server(server),
|
||||
assist_effects(AssistEffect::NONE),
|
||||
num_assist_cards_set(0),
|
||||
client_ids_with_assists(0xFF),
|
||||
active_assist_effects(AssistEffect::NONE),
|
||||
num_active_assists(0) {}
|
||||
|
||||
shared_ptr<Server> AssistServer::server() {
|
||||
auto s = this->w_server.lock();
|
||||
@@ -281,6 +277,4 @@ void AssistServer::recompute_effects() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
@@ -6,13 +6,11 @@
|
||||
#include <vector>
|
||||
|
||||
#include "DataIndex.hh"
|
||||
#include "PlayerState.hh"
|
||||
#include "DeckState.hh"
|
||||
#include "PlayerState.hh"
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
class Server;
|
||||
|
||||
extern const std::vector<uint16_t> ALL_ASSIST_CARD_IDS;
|
||||
@@ -55,6 +53,4 @@ public:
|
||||
std::shared_ptr<parray<ActionMetadata, 9>> set_card_action_metadatas[4];
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
@@ -9,8 +9,6 @@ using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
BattleRecord::Event::Event(StringReader& r) {
|
||||
this->type = r.get<Event::Type>();
|
||||
this->timestamp = r.get_u64l();
|
||||
@@ -74,19 +72,17 @@ void BattleRecord::Event::serialize(StringWriter& w) const {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
BattleRecord::BattleRecord(uint32_t behavior_flags)
|
||||
: is_writable(true),
|
||||
behavior_flags(behavior_flags),
|
||||
battle_start_timestamp(0),
|
||||
battle_end_timestamp(0) { }
|
||||
: is_writable(true),
|
||||
behavior_flags(behavior_flags),
|
||||
battle_start_timestamp(0),
|
||||
battle_end_timestamp(0) {}
|
||||
|
||||
BattleRecord::BattleRecord(const string& data)
|
||||
: is_writable(false),
|
||||
behavior_flags(0),
|
||||
battle_start_timestamp(0),
|
||||
battle_end_timestamp(0) {
|
||||
: is_writable(false),
|
||||
behavior_flags(0),
|
||||
battle_start_timestamp(0),
|
||||
battle_end_timestamp(0) {
|
||||
StringReader r(data);
|
||||
uint64_t signature = r.get_u64l();
|
||||
if (signature != this->SIGNATURE) {
|
||||
@@ -128,7 +124,6 @@ const BattleRecord::Event* BattleRecord::get_first_event() const {
|
||||
return &this->events.front();
|
||||
}
|
||||
|
||||
|
||||
void BattleRecord::add_player(
|
||||
const PlayerLobbyDataDCGC& lobby_data,
|
||||
const PlayerInventory& inventory,
|
||||
@@ -279,16 +274,14 @@ void BattleRecord::set_battle_end_timestamp() {
|
||||
this->battle_end_timestamp = now();
|
||||
}
|
||||
|
||||
|
||||
|
||||
BattleRecordPlayer::BattleRecordPlayer(
|
||||
shared_ptr<const BattleRecord> rec,
|
||||
shared_ptr<struct event_base> base)
|
||||
: record(rec),
|
||||
event_it(this->record->events.begin()),
|
||||
play_start_timestamp(0),
|
||||
base(base),
|
||||
next_command_ev(event_new(this->base.get(), -1, EV_TIMEOUT, &BattleRecordPlayer::dispatch_schedule_events, this), event_free) { }
|
||||
: record(rec),
|
||||
event_it(this->record->events.begin()),
|
||||
play_start_timestamp(0),
|
||||
base(base),
|
||||
next_command_ev(event_new(this->base.get(), -1, EV_TIMEOUT, &BattleRecordPlayer::dispatch_schedule_events, this), event_free) {}
|
||||
|
||||
shared_ptr<const BattleRecord> BattleRecordPlayer::get_record() const {
|
||||
return this->record;
|
||||
@@ -377,6 +370,4 @@ void BattleRecordPlayer::schedule_events() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <event2/event.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <phosg/Strings.hh>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
#include <phosg/Strings.hh>
|
||||
|
||||
#include "../Player.hh"
|
||||
|
||||
@@ -17,8 +17,6 @@ namespace Episode3 {
|
||||
|
||||
// The comment in Server.hh does not apply to this file (and BattleRecord.cc).
|
||||
|
||||
|
||||
|
||||
class BattleRecord {
|
||||
public:
|
||||
struct PlayerEntry {
|
||||
@@ -118,7 +116,4 @@ private:
|
||||
std::shared_ptr<struct event> next_command_ev;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
+26
-32
@@ -1,36 +1,34 @@
|
||||
#include "Card.hh"
|
||||
|
||||
#include "Server.hh"
|
||||
#include "../CommandFormats.hh"
|
||||
#include "Server.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
Card::Card(
|
||||
uint16_t card_id,
|
||||
uint16_t card_ref,
|
||||
uint16_t client_id,
|
||||
shared_ptr<Server> server)
|
||||
: w_server(server),
|
||||
w_player_state(server->get_player_state(client_id)),
|
||||
client_id(client_id),
|
||||
card_id(card_id),
|
||||
card_ref(card_ref),
|
||||
card_flags(0),
|
||||
loc(0, 0, Direction::RIGHT),
|
||||
facing_direction(Direction::INVALID_FF),
|
||||
action_chain(),
|
||||
action_metadata(),
|
||||
num_ally_fcs_destroyed_at_set_time(0),
|
||||
num_cards_destroyed_by_team_at_set_time(0),
|
||||
unknown_a9(1),
|
||||
last_attack_preliminary_damage(0),
|
||||
last_attack_final_damage(0),
|
||||
num_destroyed_ally_fcs(0),
|
||||
current_defense_power(0) { }
|
||||
: w_server(server),
|
||||
w_player_state(server->get_player_state(client_id)),
|
||||
client_id(client_id),
|
||||
card_id(card_id),
|
||||
card_ref(card_ref),
|
||||
card_flags(0),
|
||||
loc(0, 0, Direction::RIGHT),
|
||||
facing_direction(Direction::INVALID_FF),
|
||||
action_chain(),
|
||||
action_metadata(),
|
||||
num_ally_fcs_destroyed_at_set_time(0),
|
||||
num_cards_destroyed_by_team_at_set_time(0),
|
||||
unknown_a9(1),
|
||||
last_attack_preliminary_damage(0),
|
||||
last_attack_final_damage(0),
|
||||
num_destroyed_ally_fcs(0),
|
||||
current_defense_power(0) {}
|
||||
|
||||
void Card::init() {
|
||||
this->clear_action_chain_and_metadata_and_most_flags();
|
||||
@@ -117,7 +115,7 @@ ssize_t Card::apply_abnormal_condition(
|
||||
existing_cond_index = z;
|
||||
if (eff.type == ConditionType::MV_BONUS ||
|
||||
((cond.card_definition_effect_index == def_effect_index) &&
|
||||
(cond.card_ref == target_card_ref))) {
|
||||
(cond.card_ref == target_card_ref))) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -215,8 +213,8 @@ void Card::apply_ap_adjust_assists_to_attack(
|
||||
|
||||
bool Card::card_type_is_sc_or_creature() const {
|
||||
return (this->def_entry->def.type == CardType::HUNTERS_SC) ||
|
||||
(this->def_entry->def.type == CardType::ARKZ_SC) ||
|
||||
(this->def_entry->def.type == CardType::CREATURE);
|
||||
(this->def_entry->def.type == CardType::ARKZ_SC) ||
|
||||
(this->def_entry->def.type == CardType::CREATURE);
|
||||
}
|
||||
|
||||
bool Card::check_card_flag(uint32_t flags) const {
|
||||
@@ -254,7 +252,6 @@ void Card::commit_attack(
|
||||
effective_damage = 0;
|
||||
}
|
||||
|
||||
|
||||
auto attacker_ps = attacker_card->player_state();
|
||||
attacker_ps->stats.damage_given += effective_damage;
|
||||
this->player_state()->stats.damage_taken += effective_damage;
|
||||
@@ -406,13 +403,13 @@ int32_t Card::error_code_for_move_to_location(const Location& loc) const {
|
||||
return -0x60;
|
||||
}
|
||||
if (!this->server()->ruler_server->card_ref_can_move(
|
||||
this->client_id, this->card_ref, 1)) {
|
||||
this->client_id, this->card_ref, 1)) {
|
||||
return -0x7B;
|
||||
}
|
||||
// Note: The original code passes non-null pointers here but ignores the
|
||||
// values written to them; we use nulls since the behavior should be the same.
|
||||
if (!this->server()->ruler_server->get_move_path_length_and_cost(
|
||||
this->client_id, this->card_ref, loc, nullptr, nullptr)) {
|
||||
this->client_id, this->card_ref, loc, nullptr, nullptr)) {
|
||||
return -0x79;
|
||||
}
|
||||
return 0;
|
||||
@@ -556,7 +553,7 @@ int32_t Card::move_to_location(const Location& loc) {
|
||||
uint32_t path_cost;
|
||||
uint32_t path_length;
|
||||
if (!this->server()->ruler_server->get_move_path_length_and_cost(
|
||||
this->client_id, this->card_ref, loc, &path_length, &path_cost)) {
|
||||
this->client_id, this->card_ref, loc, &path_length, &path_cost)) {
|
||||
return -0x79;
|
||||
}
|
||||
|
||||
@@ -598,7 +595,6 @@ void Card::propagate_shared_hp_if_needed() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Card::send_6xB4x4E_4C_4D_if_needed(bool always_send) {
|
||||
ssize_t index = -1;
|
||||
if (this->card_ref == this->player_state()->get_sc_card_ref()) {
|
||||
@@ -940,11 +936,11 @@ void Card::unknown_80237F98(bool require_condition_20_or_21) {
|
||||
if (this->action_chain.conditions[z].type != ConditionType::NONE) {
|
||||
if (!require_condition_20_or_21 ||
|
||||
this->server()->card_special->condition_has_when_20_or_21(
|
||||
this->action_chain.conditions[z])) {
|
||||
this->action_chain.conditions[z])) {
|
||||
ActionState as;
|
||||
auto& cond = this->action_chain.conditions[z];
|
||||
if (!this->server()->card_special->is_card_targeted_by_condition(
|
||||
cond, as, this->shared_from_this())) {
|
||||
cond, as, this->shared_from_this())) {
|
||||
this->server()->card_special->apply_stat_deltas_to_card_from_condition_and_clear_cond(
|
||||
cond, this->shared_from_this());
|
||||
should_send_updates = true;
|
||||
@@ -1237,6 +1233,4 @@ void Card::unknown_80237734() {
|
||||
this->send_6xB4x4E_4C_4D_if_needed();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
@@ -4,14 +4,12 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "../Text.hh"
|
||||
#include "../CommandFormats.hh"
|
||||
#include "../Text.hh"
|
||||
#include "DataIndex.hh"
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
class ServerBase;
|
||||
class Server;
|
||||
class PlayerState;
|
||||
@@ -126,6 +124,4 @@ public:
|
||||
int16_t current_defense_power;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
+241
-236
@@ -6,8 +6,6 @@ using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
CardSpecial::DiceRoll::DiceRoll() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -20,8 +18,6 @@ void CardSpecial::DiceRoll::clear() {
|
||||
this->unknown_a5 = 0xFFFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CardSpecial::AttackEnvStats::AttackEnvStats() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -73,10 +69,9 @@ uint32_t CardSpecial::AttackEnvStats::at(size_t offset) const {
|
||||
return reinterpret_cast<const parray<uint32_t, count>*>(this)->at(offset);
|
||||
}
|
||||
|
||||
|
||||
|
||||
CardSpecial::CardSpecial(shared_ptr<Server> server)
|
||||
: w_server(server), unknown_a2(0) { }
|
||||
: w_server(server),
|
||||
unknown_a2(0) {}
|
||||
|
||||
shared_ptr<Server> CardSpecial::server() {
|
||||
auto s = this->w_server.lock();
|
||||
@@ -109,11 +104,11 @@ void CardSpecial::adjust_attack_damage_due_to_conditions(
|
||||
}
|
||||
|
||||
if (!this->server()->ruler_server->check_usability_or_apply_condition_for_card_refs(
|
||||
cond.card_ref,
|
||||
target_card->get_card_ref(),
|
||||
attacker_card_ref,
|
||||
cond.card_definition_effect_index,
|
||||
attack_medium)) {
|
||||
cond.card_ref,
|
||||
target_card->get_card_ref(),
|
||||
attacker_card_ref,
|
||||
cond.card_definition_effect_index,
|
||||
attack_medium)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -411,7 +406,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(
|
||||
if (hp != ap) {
|
||||
this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0xA0, hp - ap, 0, 0);
|
||||
this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0x20, ap - hp, 0, 0);
|
||||
card->set_current_hp(ap,1,1);
|
||||
card->set_current_hp(ap, 1, 1);
|
||||
card->ap = hp;
|
||||
this->destroy_card_if_hp_zero(card, cond_card_ref);
|
||||
}
|
||||
@@ -501,7 +496,7 @@ bool CardSpecial::card_has_condition_with_ref(
|
||||
uint16_t match_card_ref) const {
|
||||
size_t z = 0;
|
||||
while ((z < 9) &&
|
||||
((card->action_chain.conditions[z].type != cond_type) ||
|
||||
((card->action_chain.conditions[z].type != cond_type) ||
|
||||
(card->action_chain.conditions[z].card_ref == card_ref))) {
|
||||
z++;
|
||||
}
|
||||
@@ -532,7 +527,7 @@ void CardSpecial::compute_attack_ap(
|
||||
: AttackMedium::UNKNOWN;
|
||||
uint16_t target_card_ref = target_card->get_card_ref();
|
||||
|
||||
auto check_card = [&](shared_ptr<Card> card) -> void{
|
||||
auto check_card = [&](shared_ptr<Card> card) -> void {
|
||||
if (!card || (card->card_flags & 3)) {
|
||||
return;
|
||||
}
|
||||
@@ -541,19 +536,19 @@ void CardSpecial::compute_attack_ap(
|
||||
if (cond.type == ConditionType::NONE ||
|
||||
this->card_ref_has_ability_trap(cond) ||
|
||||
!this->server()->ruler_server->check_usability_or_apply_condition_for_card_refs(
|
||||
card->action_chain.conditions[cond_index].card_ref,
|
||||
target_card->get_card_ref(),
|
||||
attacker_card_ref,
|
||||
card->action_chain.conditions[cond_index].card_definition_effect_index,
|
||||
attacker_sc_attack_medium)) {
|
||||
card->action_chain.conditions[cond_index].card_ref,
|
||||
target_card->get_card_ref(),
|
||||
attacker_card_ref,
|
||||
card->action_chain.conditions[cond_index].card_definition_effect_index,
|
||||
attacker_sc_attack_medium)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto cond_type = card->action_chain.conditions[cond_index].type;
|
||||
if (((cond_type == ConditionType::UNKNOWN_5F) &&
|
||||
(target_card_ref == card->action_chain.conditions[cond_index].condition_giver_card_ref)) ||
|
||||
(target_card_ref == card->action_chain.conditions[cond_index].condition_giver_card_ref)) ||
|
||||
((cond_type == ConditionType::UNKNOWN_60) &&
|
||||
(target_card_ref == card->action_chain.conditions[cond_index].card_ref))) {
|
||||
(target_card_ref == card->action_chain.conditions[cond_index].card_ref))) {
|
||||
*out_value = card->action_chain.conditions[cond_index].value8;
|
||||
}
|
||||
}
|
||||
@@ -570,7 +565,7 @@ void CardSpecial::compute_attack_ap(
|
||||
}
|
||||
|
||||
if (attacker_card &&
|
||||
attacker_card->get_attack_condition_value(ConditionType::UNKNOWN_7D, 0xFFFF,0xFF,0xFFFF, nullptr)) {
|
||||
attacker_card->get_attack_condition_value(ConditionType::UNKNOWN_7D, 0xFFFF, 0xFF, 0xFFFF, nullptr)) {
|
||||
*out_value = *out_value * 1.5f;
|
||||
}
|
||||
if (target_card &&
|
||||
@@ -611,7 +606,8 @@ CardSpecial::AttackEnvStats CardSpecial::compute_attack_env_stats(
|
||||
ast.total_num_set_cards = ps_num_set_cards;
|
||||
|
||||
uint8_t target_card_team_id = target_card
|
||||
? target_card->player_state()->get_team_id() : 0xFF;
|
||||
? target_card->player_state()->get_team_id()
|
||||
: 0xFF;
|
||||
|
||||
size_t target_team_num_set_cards = 0;
|
||||
size_t condition_giver_team_num_set_cards = 0;
|
||||
@@ -629,19 +625,26 @@ CardSpecial::AttackEnvStats CardSpecial::compute_attack_env_stats(
|
||||
ast.condition_giver_team_num_set_cards = condition_giver_team_num_set_cards;
|
||||
|
||||
ast.num_native_creatures = this->get_all_set_cards_by_team_and_class(
|
||||
CardClass::NATIVE_CREATURE, 0xFF, true).size();
|
||||
CardClass::NATIVE_CREATURE, 0xFF, true)
|
||||
.size();
|
||||
ast.num_a_beast_creatures = this->get_all_set_cards_by_team_and_class(
|
||||
CardClass::A_BEAST_CREATURE, 0xFF, true).size();
|
||||
CardClass::A_BEAST_CREATURE, 0xFF, true)
|
||||
.size();
|
||||
ast.num_machine_creatures = this->get_all_set_cards_by_team_and_class(
|
||||
CardClass::MACHINE_CREATURE, 0xFF, true).size();
|
||||
CardClass::MACHINE_CREATURE, 0xFF, true)
|
||||
.size();
|
||||
ast.num_dark_creatures = this->get_all_set_cards_by_team_and_class(
|
||||
CardClass::DARK_CREATURE, 0xFF, true).size();
|
||||
CardClass::DARK_CREATURE, 0xFF, true)
|
||||
.size();
|
||||
ast.num_sword_type_items = this->get_all_set_cards_by_team_and_class(
|
||||
CardClass::SWORD_ITEM, 0xFF, true).size();
|
||||
CardClass::SWORD_ITEM, 0xFF, true)
|
||||
.size();
|
||||
ast.num_gun_type_items = this->get_all_set_cards_by_team_and_class(
|
||||
CardClass::GUN_ITEM, 0xFF, true).size();
|
||||
CardClass::GUN_ITEM, 0xFF, true)
|
||||
.size();
|
||||
ast.num_cane_type_items = this->get_all_set_cards_by_team_and_class(
|
||||
CardClass::CANE_ITEM, 0xFF, true).size();
|
||||
CardClass::CANE_ITEM, 0xFF, true)
|
||||
.size();
|
||||
ast.num_sword_type_items_on_team = card
|
||||
? this->get_all_set_cards_by_team_and_class(CardClass::SWORD_ITEM, card->get_team_id(), true).size()
|
||||
: 0;
|
||||
@@ -672,11 +675,14 @@ CardSpecial::AttackEnvStats CardSpecial::compute_attack_env_stats(
|
||||
ast.team_dice_boost = card ? this->server()->team_dice_boost[card->get_team_id()] : 0;
|
||||
|
||||
ast.effective_ap_if_not_tech = (!attacker_card || (attacker_card->action_chain.chain.attack_medium == AttackMedium::TECH))
|
||||
? 0 : attacker_card->action_chain.chain.damage;
|
||||
? 0
|
||||
: attacker_card->action_chain.chain.damage;
|
||||
ast.effective_ap_if_not_tech2 = (!attacker_card || (attacker_card->action_chain.chain.attack_medium == AttackMedium::TECH))
|
||||
? 0 : attacker_card->action_chain.chain.damage;
|
||||
? 0
|
||||
: attacker_card->action_chain.chain.damage;
|
||||
ast.effective_ap_if_not_physical = (!attacker_card || (attacker_card->action_chain.chain.attack_medium == AttackMedium::PHYSICAL))
|
||||
? 0 : attacker_card->action_chain.chain.damage;
|
||||
? 0
|
||||
: attacker_card->action_chain.chain.damage;
|
||||
ast.sc_effective_ap = attacker_card ? attacker_card->action_chain.chain.damage : 0;
|
||||
ast.attack_bonus = card->action_metadata.attack_bonus;
|
||||
ast.last_attack_preliminary_damage = card->last_attack_preliminary_damage;
|
||||
@@ -707,7 +713,8 @@ CardSpecial::AttackEnvStats CardSpecial::compute_attack_env_stats(
|
||||
// original code.
|
||||
for (z = 0;
|
||||
((target_card_ref != pa.attacker_card_ref) && (z < 9) && (pa.action_card_refs[z] != 0xFFFF));
|
||||
z++) { }
|
||||
z++) {
|
||||
}
|
||||
ast.action_cards_ap = 0;
|
||||
ast.action_cards_tp = 0;
|
||||
for (; (z < 9) && (pa.action_card_refs[z] != 0xFFFF); z++) {
|
||||
@@ -789,11 +796,11 @@ shared_ptr<Card> CardSpecial::compute_replaced_target_based_on_conditions(
|
||||
continue;
|
||||
}
|
||||
if (!this->server()->ruler_server->check_usability_or_apply_condition_for_card_refs(
|
||||
target_card->action_chain.conditions[x].card_ref,
|
||||
target_card->get_card_ref(),
|
||||
attacker_card_ref,
|
||||
target_card->action_chain.conditions[x].card_definition_effect_index,
|
||||
attack_medium)) {
|
||||
target_card->action_chain.conditions[x].card_ref,
|
||||
target_card->get_card_ref(),
|
||||
attacker_card_ref,
|
||||
target_card->action_chain.conditions[x].card_definition_effect_index,
|
||||
attack_medium)) {
|
||||
continue;
|
||||
}
|
||||
if (target_card->action_chain.conditions[x].type != ConditionType::PARRY) {
|
||||
@@ -871,11 +878,11 @@ shared_ptr<Card> CardSpecial::compute_replaced_target_based_on_conditions(
|
||||
continue;
|
||||
}
|
||||
if (!this->server()->ruler_server->check_usability_or_apply_condition_for_card_refs(
|
||||
other_set_card->action_chain.conditions[z].card_ref,
|
||||
other_set_card->get_card_ref(),
|
||||
attacker_card_ref,
|
||||
other_set_card->action_chain.conditions[z].card_definition_effect_index,
|
||||
attack_medium)) {
|
||||
other_set_card->action_chain.conditions[z].card_ref,
|
||||
other_set_card->get_card_ref(),
|
||||
attacker_card_ref,
|
||||
other_set_card->action_chain.conditions[z].card_definition_effect_index,
|
||||
attack_medium)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -896,9 +903,9 @@ shared_ptr<Card> CardSpecial::compute_replaced_target_based_on_conditions(
|
||||
(unknown_p4 != 0) &&
|
||||
(target_card_ref == other_set_card->action_chain.conditions[z].condition_giver_card_ref)) {
|
||||
candidate_cards.emplace_back(other_set_card);
|
||||
if (unknown_p11 &&(def_effect_index != 0xFF) && (set_card_ref != 0xFFFF) &&
|
||||
if (unknown_p11 && (def_effect_index != 0xFF) && (set_card_ref != 0xFFFF) &&
|
||||
!this->server()->ruler_server->check_usability_or_apply_condition_for_card_refs(
|
||||
set_card_ref, sc_card_ref, other_set_card->get_card_ref(), def_effect_index, attack_medium)) {
|
||||
set_card_ref, sc_card_ref, other_set_card->get_card_ref(), def_effect_index, attack_medium)) {
|
||||
*unknown_p11 = 1;
|
||||
}
|
||||
}
|
||||
@@ -950,11 +957,11 @@ shared_ptr<Card> CardSpecial::compute_replaced_target_based_on_conditions(
|
||||
continue;
|
||||
}
|
||||
if (!this->server()->ruler_server->check_usability_or_apply_condition_for_card_refs(
|
||||
cond.card_ref,
|
||||
other_sc->get_card_ref(),
|
||||
attacker_card_ref,
|
||||
cond.card_definition_effect_index,
|
||||
attack_medium)) {
|
||||
cond.card_ref,
|
||||
other_sc->get_card_ref(),
|
||||
attacker_card_ref,
|
||||
cond.card_definition_effect_index,
|
||||
attack_medium)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -977,7 +984,7 @@ shared_ptr<Card> CardSpecial::compute_replaced_target_based_on_conditions(
|
||||
candidate_cards.emplace_back(other_sc);
|
||||
if (unknown_p11 && (def_effect_index != 0xFF) && (set_card_ref != 0xFFFF) &&
|
||||
!this->server()->ruler_server->check_usability_or_apply_condition_for_card_refs(
|
||||
set_card_ref, sc_card_ref, other_sc->get_card_ref(), def_effect_index, attack_medium)) {
|
||||
set_card_ref, sc_card_ref, other_sc->get_card_ref(), def_effect_index, attack_medium)) {
|
||||
*unknown_p11 = 1;
|
||||
}
|
||||
}
|
||||
@@ -1262,7 +1269,7 @@ bool CardSpecial::evaluate_effect_arg2_condition(
|
||||
|
||||
auto set_card = this->server()->card_for_set_card_ref(set_card_ref);
|
||||
bool set_card_has_ability_trap = (set_card &&
|
||||
(this->card_has_condition_with_ref(set_card, ConditionType::ABILITY_TRAP, 0xFFFF, 0xFFFF)));
|
||||
(this->card_has_condition_with_ref(set_card, ConditionType::ABILITY_TRAP, 0xFFFF, 0xFFFF)));
|
||||
|
||||
switch (arg2_text[0]) {
|
||||
case 'C':
|
||||
@@ -1392,15 +1399,15 @@ bool CardSpecial::evaluate_effect_arg2_condition(
|
||||
case 13: {
|
||||
auto ce = card->get_definition();
|
||||
return ((ce->def.card_class() == CardClass::GUARD_ITEM) ||
|
||||
(ce->def.card_class() == CardClass::MAG_ITEM) ||
|
||||
this->server()->ruler_server->find_condition_on_card_ref(
|
||||
card->get_card_ref(), ConditionType::GUARD_CREATURE, 0, 0, 0));
|
||||
(ce->def.card_class() == CardClass::MAG_ITEM) ||
|
||||
this->server()->ruler_server->find_condition_on_card_ref(
|
||||
card->get_card_ref(), ConditionType::GUARD_CREATURE, 0, 0, 0));
|
||||
}
|
||||
case 14:
|
||||
return card->get_definition()->def.is_sc();
|
||||
case 15:
|
||||
return ((card->action_chain.chain.attack_action_card_ref_count == 0) &&
|
||||
(card->action_metadata.defense_card_ref_count == 0));
|
||||
(card->action_metadata.defense_card_ref_count == 0));
|
||||
case 16:
|
||||
return this->server()->ruler_server->card_ref_is_aerial(card->get_card_ref());
|
||||
case 17: {
|
||||
@@ -1462,14 +1469,14 @@ bool CardSpecial::evaluate_effect_arg2_condition(
|
||||
}
|
||||
}
|
||||
return (this->find_condition_with_parameters(
|
||||
card, ConditionType::ANY, set_card_ref, ((v % 10) == 0) ? 0xFF : (v % 10)) != nullptr);
|
||||
card, ConditionType::ANY, set_card_ref, ((v % 10) == 0) ? 0xFF : (v % 10)) != nullptr);
|
||||
}
|
||||
case 'r':
|
||||
return !set_card_has_ability_trap && (random_percent < atoi(arg2_text + 1));
|
||||
case 's': {
|
||||
auto ce = card->get_definition();
|
||||
return ((ce->def.self_cost >= arg2_text[1] - '0') &&
|
||||
(ce->def.self_cost <= arg2_text[2] - '0'));
|
||||
(ce->def.self_cost <= arg2_text[2] - '0'));
|
||||
}
|
||||
case 't': {
|
||||
auto set_card = this->server()->card_for_set_card_ref(set_card_ref);
|
||||
@@ -1597,8 +1604,8 @@ bool CardSpecial::execute_effect(
|
||||
|
||||
if ((card->card_flags & 3) ||
|
||||
(card->action_metadata.check_flag(0x10) &&
|
||||
(cond.card_ref != card->get_card_ref()) &&
|
||||
(cond.condition_giver_card_ref != card->get_card_ref()))) {
|
||||
(cond.card_ref != card->get_card_ref()) &&
|
||||
(cond.condition_giver_card_ref != card->get_card_ref()))) {
|
||||
unknown_p7 = unknown_p7 & 0xFFFFFFFB;
|
||||
}
|
||||
if (unknown_p7 == 0) {
|
||||
@@ -1887,8 +1894,7 @@ bool CardSpecial::execute_effect(
|
||||
|
||||
case ConditionType::BONUS_FROM_LEADER:
|
||||
if (unknown_p7 & 1) {
|
||||
clamped_unknown_p5 = this->count_cards_with_card_id_set_by_player_except_card_ref(expr_value, 0xFFFF)
|
||||
+ (card->action_chain).chain.ap_effect_bonus;
|
||||
clamped_unknown_p5 = this->count_cards_with_card_id_set_by_player_except_card_ref(expr_value, 0xFFFF) + (card->action_chain).chain.ap_effect_bonus;
|
||||
(card->action_chain).chain.ap_effect_bonus = clamp<int16_t>(clamped_unknown_p5, -99, 99);
|
||||
}
|
||||
return true;
|
||||
@@ -2069,9 +2075,9 @@ bool CardSpecial::execute_effect(
|
||||
auto sc_card = this->server()->card_for_set_card_ref(card_ref);
|
||||
if (sc_card && (sc_card->get_current_hp() > 0)) {
|
||||
if (this->server()->ruler_server->check_usability_or_apply_condition_for_card_refs(
|
||||
cond.card_ref, cond.condition_giver_card_ref,
|
||||
sc_card->get_card_ref(), cond.card_definition_effect_index,
|
||||
attack_medium)) {
|
||||
cond.card_ref, cond.condition_giver_card_ref,
|
||||
sc_card->get_card_ref(), cond.card_definition_effect_index,
|
||||
attack_medium)) {
|
||||
this->send_6xB4x06_for_stat_delta(sc_card, attacker_card_ref, 0x20, -sc_card->get_current_hp(), 0, 1);
|
||||
sc_card->set_current_hp(0);
|
||||
this->destroy_card_if_hp_zero(sc_card, attacker_card_ref);
|
||||
@@ -2288,11 +2294,11 @@ bool CardSpecial::execute_effect(
|
||||
auto set_card = this->server()->card_for_set_card_ref(card_ref);
|
||||
if (set_card && (set_card->get_current_hp() > 0)) {
|
||||
if (this->server()->ruler_server->check_usability_or_apply_condition_for_card_refs(
|
||||
cond.card_ref,
|
||||
cond.condition_giver_card_ref,
|
||||
set_card->get_card_ref(),
|
||||
cond.card_definition_effect_index,
|
||||
attack_medium)) {
|
||||
cond.card_ref,
|
||||
cond.condition_giver_card_ref,
|
||||
set_card->get_card_ref(),
|
||||
cond.card_definition_effect_index,
|
||||
attack_medium)) {
|
||||
this->send_6xB4x06_for_stat_delta(
|
||||
set_card, attacker_card_ref, 0x20, -set_card->get_current_hp(), 0, 1);
|
||||
set_card->set_current_hp(0);
|
||||
@@ -2391,7 +2397,7 @@ void CardSpecial::get_effective_ap_tp(
|
||||
}
|
||||
|
||||
const char* CardSpecial::get_next_expr_token(
|
||||
const char *expr, ExpressionTokenType* out_type, int32_t* out_value) const {
|
||||
const char* expr, ExpressionTokenType* out_type, int32_t* out_value) const {
|
||||
switch (*expr) {
|
||||
case '\0':
|
||||
*out_type = ExpressionTokenType::SPACE;
|
||||
@@ -2427,11 +2433,11 @@ const char* CardSpecial::get_next_expr_token(
|
||||
*out_type = ExpressionTokenType::SPACE;
|
||||
*out_value = 0x27;
|
||||
|
||||
static const vector<const char*> tokens({
|
||||
static const vector<const char*> tokens = {
|
||||
"f", "d", "ap", "tp", "hp", "mhp", "dm", "tdm", "tf", "ac", "php",
|
||||
"dc", "cs", "a", "kap", "ktp", "dn", "hf", "df", "ff", "ef", "bi",
|
||||
"ab", "mc", "dk", "sa", "gn", "wd", "tt", "lv", "adm", "ddm", "sat",
|
||||
"edm", "ldm", "rdm", "fdm", "ndm", "ehp"});
|
||||
"edm", "ldm", "rdm", "fdm", "ndm", "ehp"};
|
||||
for (size_t z = 0; z < tokens.size(); z++) {
|
||||
if (token_buf == tokens[z]) {
|
||||
*out_type = ExpressionTokenType::REFERENCE;
|
||||
@@ -2467,7 +2473,8 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
}
|
||||
|
||||
auto card2 = this->server()->card_for_set_card_ref((as.attacker_card_ref == 0xFFFF)
|
||||
? as.original_attacker_card_ref : as.attacker_card_ref);
|
||||
? as.original_attacker_card_ref
|
||||
: as.attacker_card_ref);
|
||||
|
||||
Location card1_loc;
|
||||
if (!card1) {
|
||||
@@ -2526,7 +2533,8 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
break;
|
||||
case 4:
|
||||
size_t z;
|
||||
for (z = 0; (z < 9) && (as.action_card_refs[z] != 0xFFFF) && (as.action_card_refs[z] != card_ref); z++) { }
|
||||
for (z = 0; (z < 9) && (as.action_card_refs[z] != 0xFFFF) && (as.action_card_refs[z] != card_ref); z++) {
|
||||
}
|
||||
for (; (z < 9) && (as.action_card_refs[z] != 0xFFFF); z++) {
|
||||
auto result_card = this->server()->card_for_set_card_ref(as.action_card_refs[z]);
|
||||
if (result_card) {
|
||||
@@ -2971,7 +2979,7 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
auto result_card = ps->get_set_card(set_index);
|
||||
if (result_card && (card1 != result_card) &&
|
||||
(result_card->get_definition()->def.type == CardType::ITEM)) {
|
||||
(result_card->get_definition()->def.type == CardType::ITEM)) {
|
||||
bool should_add = true;
|
||||
for (auto c : ret) {
|
||||
if (c == result_card) {
|
||||
@@ -2992,7 +3000,7 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
vector<shared_ptr<const Card>> filtered_ret;
|
||||
for (auto c : ret) {
|
||||
if (this->server()->ruler_server->check_usability_or_apply_condition_for_card_refs(
|
||||
card_ref, setter_card_ref, c->get_card_ref(), def_effect_index, attack_medium)) {
|
||||
card_ref, setter_card_ref, c->get_card_ref(), def_effect_index, attack_medium)) {
|
||||
filtered_ret.emplace_back(c);
|
||||
}
|
||||
}
|
||||
@@ -3176,8 +3184,8 @@ bool CardSpecial::should_cancel_condition_due_to_anti_abnormality(
|
||||
}
|
||||
if ((card->card_flags & 3) ||
|
||||
(card->action_metadata.check_flag(0x10) &&
|
||||
(card->get_card_ref() != target_card_ref) &&
|
||||
(card->get_card_ref() != sc_card_ref))) {
|
||||
(card->get_card_ref() != target_card_ref) &&
|
||||
(card->get_card_ref() != sc_card_ref))) {
|
||||
return true;
|
||||
}
|
||||
auto ce = card->get_definition();
|
||||
@@ -3519,15 +3527,15 @@ void CardSpecial::unknown_8024C2B0(
|
||||
bool all_targets_matched = false;
|
||||
if (!targeted_cards.empty() &&
|
||||
((card_effect.type == ConditionType::UNKNOWN_64) ||
|
||||
(card_effect.type == ConditionType::MISC_DEFENSE_BONUSES) ||
|
||||
(card_effect.type == ConditionType::MOSTLY_HALFGUARDS))) {
|
||||
(card_effect.type == ConditionType::MISC_DEFENSE_BONUSES) ||
|
||||
(card_effect.type == ConditionType::MOSTLY_HALFGUARDS))) {
|
||||
size_t count = 0;
|
||||
for (size_t z = 0; z < targeted_cards.size(); z++) {
|
||||
dice_roll.value_used_in_expr = false;
|
||||
string arg2_text = card_effect.arg2;
|
||||
if (this->evaluate_effect_arg2_condition(
|
||||
as, targeted_cards[z], arg2_text.c_str(), dice_roll,
|
||||
set_card_ref, sc_card_ref, random_percent, when)) {
|
||||
as, targeted_cards[z], arg2_text.c_str(), dice_roll,
|
||||
set_card_ref, sc_card_ref, random_percent, when)) {
|
||||
count++;
|
||||
}
|
||||
if (dice_roll.value_used_in_expr) {
|
||||
@@ -3554,7 +3562,7 @@ void CardSpecial::unknown_8024C2B0(
|
||||
string arg2_str = card_effect.arg2;
|
||||
if (all_targets_matched ||
|
||||
this->evaluate_effect_arg2_condition(
|
||||
as, targeted_cards[z], arg2_str.c_str(), dice_roll, set_card_ref, sc_card_ref, random_percent, when)) {
|
||||
as, targeted_cards[z], arg2_str.c_str(), dice_roll, set_card_ref, sc_card_ref, random_percent, when)) {
|
||||
auto env_stats = this->compute_attack_env_stats(
|
||||
as, targeted_cards[z], dice_roll, set_card_ref, sc_card_ref);
|
||||
string expr_str = card_effect.expr;
|
||||
@@ -3577,8 +3585,7 @@ void CardSpecial::unknown_8024C2B0(
|
||||
}
|
||||
|
||||
ssize_t applied_cond_index = -1;
|
||||
if ((unknown_v1 == 0) && !this->should_cancel_condition_due_to_anti_abnormality(
|
||||
card_effect, target_card, dice_cmd.effect.target_card_ref, sc_card_ref)) {
|
||||
if ((unknown_v1 == 0) && !this->should_cancel_condition_due_to_anti_abnormality(card_effect, target_card, dice_cmd.effect.target_card_ref, sc_card_ref)) {
|
||||
applied_cond_index = target_card->apply_abnormal_condition(
|
||||
card_effect, def_effect_index, dice_cmd.effect.target_card_ref, sc_card_ref, value, dice_roll.value, random_percent);
|
||||
// This debug_print call is in the original code.
|
||||
@@ -3713,152 +3720,152 @@ const InterferenceProbabilityEntry* get_interference_probability_entry(
|
||||
uint16_t column_card_id,
|
||||
bool is_attack) {
|
||||
static const InterferenceProbabilityEntry entries[] = {
|
||||
{0x0004, 0xFF, 0xFF},
|
||||
{0x0002, 0x04, 0x00},
|
||||
{0x0002, 0x00, 0x0F},
|
||||
{0x0003, 0x03, 0x00},
|
||||
{0x0003, 0x00, 0x0A},
|
||||
{0x0006, 0x01, 0x00},
|
||||
{0x0006, 0x00, 0x05},
|
||||
{0x0111, 0x01, 0x00},
|
||||
{0x0111, 0x00, 0x05},
|
||||
{0x0001, 0x03, 0x00},
|
||||
{0x0001, 0x00, 0x0A},
|
||||
{0x0002, 0xFF, 0xFF},
|
||||
{0x0004, 0x04, 0x00},
|
||||
{0x0004, 0x00, 0x0F},
|
||||
{0x0003, 0x06, 0x00},
|
||||
{0x0003, 0x00, 0x14},
|
||||
{0x0006, 0x04, 0x00},
|
||||
{0x0006, 0x00, 0x0F},
|
||||
{0x0003, 0xFF, 0xFF},
|
||||
{0x0004, 0x04, 0x00},
|
||||
{0x0004, 0x00, 0x0F},
|
||||
{0x0002, 0x04, 0x00},
|
||||
{0x0002, 0x00, 0x0F},
|
||||
{0x0006, 0xFF, 0xFF},
|
||||
{0x0002, 0x06, 0x00},
|
||||
{0x0002, 0x00, 0x14},
|
||||
{0x0111, 0xFF, 0xFF},
|
||||
{0x0004, 0x01, 0x00},
|
||||
{0x0004, 0x00, 0x05},
|
||||
{0x0001, 0x06, 0x00},
|
||||
{0x0001, 0x00, 0x14},
|
||||
{0x0001, 0xFF, 0xFF},
|
||||
{0x0111, 0x04, 0x00},
|
||||
{0x0111, 0x00, 0x0F},
|
||||
{0x0112, 0xFF, 0xFF},
|
||||
{0x0113, 0x06, 0x00},
|
||||
{0x0113, 0x00, 0x14},
|
||||
{0x0110, 0x06, 0x00},
|
||||
{0x0110, 0x00, 0x14},
|
||||
{0x0114, 0x01, 0x00},
|
||||
{0x0114, 0x00, 0x05},
|
||||
{0x011D, 0x02, 0x00},
|
||||
{0x011D, 0x00, 0x07},
|
||||
{0x0113, 0xFF, 0xFF},
|
||||
{0x0003, 0x03, 0x00},
|
||||
{0x0003, 0x00, 0x0A},
|
||||
{0x0112, 0x03, 0x00},
|
||||
{0x0112, 0x00, 0x0A},
|
||||
{0x0110, 0xFF, 0xFF},
|
||||
{0x0005, 0x03, 0x00},
|
||||
{0x0005, 0x00, 0x0A},
|
||||
{0x0112, 0x04, 0x00},
|
||||
{0x0112, 0x00, 0x0F},
|
||||
{0x0005, 0xFF, 0xFF},
|
||||
{0x0110, 0x03, 0x00},
|
||||
{0x0110, 0x00, 0x0A},
|
||||
{0x0114, 0xFF, 0xFF},
|
||||
{0x0005, 0x03, 0x00},
|
||||
{0x0005, 0x00, 0x0A},
|
||||
{0x0110, 0x01, 0x00},
|
||||
{0x0110, 0x00, 0x05},
|
||||
{0x0115, 0x06, 0x00},
|
||||
{0x0115, 0x00, 0x14},
|
||||
{0x0115, 0xFF, 0xFF},
|
||||
{0x0004, 0x01, 0x00},
|
||||
{0x0004, 0x00, 0x05},
|
||||
{0x0003, 0x01, 0x00},
|
||||
{0x0003, 0x00, 0x05},
|
||||
{0x0006, 0x01, 0x00},
|
||||
{0x0006, 0x00, 0x05},
|
||||
{0x0112, 0x01, 0x00},
|
||||
{0x0112, 0x00, 0x05},
|
||||
{0x0110, 0x01, 0x00},
|
||||
{0x0110, 0x00, 0x05},
|
||||
{0x0114, 0x04, 0x00},
|
||||
{0x0114, 0x00, 0x0F},
|
||||
{0x0008, 0xFF, 0xFF},
|
||||
{0x0007, 0x06, 0x00},
|
||||
{0x0007, 0x00, 0x14},
|
||||
{0x0116, 0x01, 0x00},
|
||||
{0x0116, 0x00, 0x05},
|
||||
{0x011E, 0x03, 0x00},
|
||||
{0x011E, 0x00, 0x0A},
|
||||
{0x0118, 0x06, 0x00},
|
||||
{0x0118, 0x00, 0x14},
|
||||
{0x0007, 0xFF, 0xFF},
|
||||
{0x0008, 0x06, 0x00},
|
||||
{0x0008, 0x00, 0x14},
|
||||
{0x0118, 0x01, 0x00},
|
||||
{0x0118, 0x00, 0x05},
|
||||
{0x011B, 0x03, 0x00},
|
||||
{0x011B, 0x00, 0x0A},
|
||||
{0x0116, 0xFF, 0xFF},
|
||||
{0x0008, 0x01, 0x00},
|
||||
{0x0008, 0x00, 0x05},
|
||||
{0x011C, 0x03, 0x00},
|
||||
{0x011C, 0x00, 0x0A},
|
||||
{0x011A, 0xFF, 0xFF},
|
||||
{0x0119, 0x04, 0x00},
|
||||
{0x0119, 0x00, 0x0F},
|
||||
{0x011D, 0x04, 0x00},
|
||||
{0x011D, 0x00, 0x0F},
|
||||
{0x0119, 0xFF, 0xFF},
|
||||
{0x011A, 0x04, 0x00},
|
||||
{0x011A, 0x00, 0x0F},
|
||||
{0x011D, 0x04, 0x00},
|
||||
{0x011D, 0x00, 0x0F},
|
||||
{0x011D, 0xFF, 0xFF},
|
||||
{0x0119, 0x04, 0x00},
|
||||
{0x0119, 0x00, 0x0F},
|
||||
{0x011A, 0x04, 0x00},
|
||||
{0x011A, 0x00, 0x0F},
|
||||
{0x0112, 0x01, 0x00},
|
||||
{0x0112, 0x00, 0x07},
|
||||
{0x011E, 0xFF, 0xFF},
|
||||
{0x0008, 0x03, 0x00},
|
||||
{0x0008, 0x00, 0x0A},
|
||||
{0x0118, 0x06, 0x00},
|
||||
{0x0118, 0x00, 0x14},
|
||||
{0x011C, 0xFF, 0xFF},
|
||||
{0x0116, 0x04, 0x00},
|
||||
{0x0116, 0x00, 0x0F},
|
||||
{0x011E, 0x01, 0x00},
|
||||
{0x011E, 0x00, 0x05},
|
||||
{0x0118, 0xFF, 0xFF},
|
||||
{0x011E, 0x06, 0x00},
|
||||
{0x011E, 0x00, 0x14},
|
||||
{0x011B, 0xFF, 0xFF},
|
||||
{0x0007, 0x03, 0x00},
|
||||
{0x0007, 0x00, 0x0A},
|
||||
{0x0117, 0x03, 0x00},
|
||||
{0x0117, 0x00, 0x0A},
|
||||
{0x011F, 0x06, 0x00},
|
||||
{0x011F, 0x00, 0x14},
|
||||
{0x0117, 0xFF, 0xFF},
|
||||
{0x011F, 0x03, 0x00},
|
||||
{0x011F, 0x00, 0x0A},
|
||||
{0x011B, 0x04, 0x00},
|
||||
{0x011B, 0x00, 0x0F},
|
||||
{0x011F, 0xFF, 0xFF},
|
||||
{0x0007, 0x01, 0x00},
|
||||
{0x0007, 0x00, 0x05},
|
||||
{0x011B, 0x06, 0x00},
|
||||
{0x011B, 0x00, 0x14},
|
||||
{0x0117, 0x04, 0x00},
|
||||
{0x0117, 0x00, 0x0F},
|
||||
{0x0004, 0xFF, 0xFF},
|
||||
{0x0002, 0x04, 0x00},
|
||||
{0x0002, 0x00, 0x0F},
|
||||
{0x0003, 0x03, 0x00},
|
||||
{0x0003, 0x00, 0x0A},
|
||||
{0x0006, 0x01, 0x00},
|
||||
{0x0006, 0x00, 0x05},
|
||||
{0x0111, 0x01, 0x00},
|
||||
{0x0111, 0x00, 0x05},
|
||||
{0x0001, 0x03, 0x00},
|
||||
{0x0001, 0x00, 0x0A},
|
||||
{0x0002, 0xFF, 0xFF},
|
||||
{0x0004, 0x04, 0x00},
|
||||
{0x0004, 0x00, 0x0F},
|
||||
{0x0003, 0x06, 0x00},
|
||||
{0x0003, 0x00, 0x14},
|
||||
{0x0006, 0x04, 0x00},
|
||||
{0x0006, 0x00, 0x0F},
|
||||
{0x0003, 0xFF, 0xFF},
|
||||
{0x0004, 0x04, 0x00},
|
||||
{0x0004, 0x00, 0x0F},
|
||||
{0x0002, 0x04, 0x00},
|
||||
{0x0002, 0x00, 0x0F},
|
||||
{0x0006, 0xFF, 0xFF},
|
||||
{0x0002, 0x06, 0x00},
|
||||
{0x0002, 0x00, 0x14},
|
||||
{0x0111, 0xFF, 0xFF},
|
||||
{0x0004, 0x01, 0x00},
|
||||
{0x0004, 0x00, 0x05},
|
||||
{0x0001, 0x06, 0x00},
|
||||
{0x0001, 0x00, 0x14},
|
||||
{0x0001, 0xFF, 0xFF},
|
||||
{0x0111, 0x04, 0x00},
|
||||
{0x0111, 0x00, 0x0F},
|
||||
{0x0112, 0xFF, 0xFF},
|
||||
{0x0113, 0x06, 0x00},
|
||||
{0x0113, 0x00, 0x14},
|
||||
{0x0110, 0x06, 0x00},
|
||||
{0x0110, 0x00, 0x14},
|
||||
{0x0114, 0x01, 0x00},
|
||||
{0x0114, 0x00, 0x05},
|
||||
{0x011D, 0x02, 0x00},
|
||||
{0x011D, 0x00, 0x07},
|
||||
{0x0113, 0xFF, 0xFF},
|
||||
{0x0003, 0x03, 0x00},
|
||||
{0x0003, 0x00, 0x0A},
|
||||
{0x0112, 0x03, 0x00},
|
||||
{0x0112, 0x00, 0x0A},
|
||||
{0x0110, 0xFF, 0xFF},
|
||||
{0x0005, 0x03, 0x00},
|
||||
{0x0005, 0x00, 0x0A},
|
||||
{0x0112, 0x04, 0x00},
|
||||
{0x0112, 0x00, 0x0F},
|
||||
{0x0005, 0xFF, 0xFF},
|
||||
{0x0110, 0x03, 0x00},
|
||||
{0x0110, 0x00, 0x0A},
|
||||
{0x0114, 0xFF, 0xFF},
|
||||
{0x0005, 0x03, 0x00},
|
||||
{0x0005, 0x00, 0x0A},
|
||||
{0x0110, 0x01, 0x00},
|
||||
{0x0110, 0x00, 0x05},
|
||||
{0x0115, 0x06, 0x00},
|
||||
{0x0115, 0x00, 0x14},
|
||||
{0x0115, 0xFF, 0xFF},
|
||||
{0x0004, 0x01, 0x00},
|
||||
{0x0004, 0x00, 0x05},
|
||||
{0x0003, 0x01, 0x00},
|
||||
{0x0003, 0x00, 0x05},
|
||||
{0x0006, 0x01, 0x00},
|
||||
{0x0006, 0x00, 0x05},
|
||||
{0x0112, 0x01, 0x00},
|
||||
{0x0112, 0x00, 0x05},
|
||||
{0x0110, 0x01, 0x00},
|
||||
{0x0110, 0x00, 0x05},
|
||||
{0x0114, 0x04, 0x00},
|
||||
{0x0114, 0x00, 0x0F},
|
||||
{0x0008, 0xFF, 0xFF},
|
||||
{0x0007, 0x06, 0x00},
|
||||
{0x0007, 0x00, 0x14},
|
||||
{0x0116, 0x01, 0x00},
|
||||
{0x0116, 0x00, 0x05},
|
||||
{0x011E, 0x03, 0x00},
|
||||
{0x011E, 0x00, 0x0A},
|
||||
{0x0118, 0x06, 0x00},
|
||||
{0x0118, 0x00, 0x14},
|
||||
{0x0007, 0xFF, 0xFF},
|
||||
{0x0008, 0x06, 0x00},
|
||||
{0x0008, 0x00, 0x14},
|
||||
{0x0118, 0x01, 0x00},
|
||||
{0x0118, 0x00, 0x05},
|
||||
{0x011B, 0x03, 0x00},
|
||||
{0x011B, 0x00, 0x0A},
|
||||
{0x0116, 0xFF, 0xFF},
|
||||
{0x0008, 0x01, 0x00},
|
||||
{0x0008, 0x00, 0x05},
|
||||
{0x011C, 0x03, 0x00},
|
||||
{0x011C, 0x00, 0x0A},
|
||||
{0x011A, 0xFF, 0xFF},
|
||||
{0x0119, 0x04, 0x00},
|
||||
{0x0119, 0x00, 0x0F},
|
||||
{0x011D, 0x04, 0x00},
|
||||
{0x011D, 0x00, 0x0F},
|
||||
{0x0119, 0xFF, 0xFF},
|
||||
{0x011A, 0x04, 0x00},
|
||||
{0x011A, 0x00, 0x0F},
|
||||
{0x011D, 0x04, 0x00},
|
||||
{0x011D, 0x00, 0x0F},
|
||||
{0x011D, 0xFF, 0xFF},
|
||||
{0x0119, 0x04, 0x00},
|
||||
{0x0119, 0x00, 0x0F},
|
||||
{0x011A, 0x04, 0x00},
|
||||
{0x011A, 0x00, 0x0F},
|
||||
{0x0112, 0x01, 0x00},
|
||||
{0x0112, 0x00, 0x07},
|
||||
{0x011E, 0xFF, 0xFF},
|
||||
{0x0008, 0x03, 0x00},
|
||||
{0x0008, 0x00, 0x0A},
|
||||
{0x0118, 0x06, 0x00},
|
||||
{0x0118, 0x00, 0x14},
|
||||
{0x011C, 0xFF, 0xFF},
|
||||
{0x0116, 0x04, 0x00},
|
||||
{0x0116, 0x00, 0x0F},
|
||||
{0x011E, 0x01, 0x00},
|
||||
{0x011E, 0x00, 0x05},
|
||||
{0x0118, 0xFF, 0xFF},
|
||||
{0x011E, 0x06, 0x00},
|
||||
{0x011E, 0x00, 0x14},
|
||||
{0x011B, 0xFF, 0xFF},
|
||||
{0x0007, 0x03, 0x00},
|
||||
{0x0007, 0x00, 0x0A},
|
||||
{0x0117, 0x03, 0x00},
|
||||
{0x0117, 0x00, 0x0A},
|
||||
{0x011F, 0x06, 0x00},
|
||||
{0x011F, 0x00, 0x14},
|
||||
{0x0117, 0xFF, 0xFF},
|
||||
{0x011F, 0x03, 0x00},
|
||||
{0x011F, 0x00, 0x0A},
|
||||
{0x011B, 0x04, 0x00},
|
||||
{0x011B, 0x00, 0x0F},
|
||||
{0x011F, 0xFF, 0xFF},
|
||||
{0x0007, 0x01, 0x00},
|
||||
{0x0007, 0x00, 0x05},
|
||||
{0x011B, 0x06, 0x00},
|
||||
{0x011B, 0x00, 0x14},
|
||||
{0x0117, 0x04, 0x00},
|
||||
{0x0117, 0x00, 0x0F},
|
||||
};
|
||||
constexpr size_t num_entries = sizeof(entries) / sizeof(entries[0]);
|
||||
|
||||
@@ -4526,6 +4533,4 @@ vector<shared_ptr<const Card>> CardSpecial::find_all_sc_cards_of_class(
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
struct InterferenceProbabilityEntry {
|
||||
uint16_t card_id;
|
||||
uint8_t attack_probability;
|
||||
@@ -22,8 +20,6 @@ const InterferenceProbabilityEntry* get_interference_probability_entry(
|
||||
uint16_t column_card_id,
|
||||
bool is_attack);
|
||||
|
||||
|
||||
|
||||
class CardSpecial {
|
||||
public:
|
||||
enum class ExpressionTokenType {
|
||||
@@ -224,7 +220,7 @@ public:
|
||||
int16_t ap,
|
||||
int16_t tp);
|
||||
const char* get_next_expr_token(
|
||||
const char *expr, ExpressionTokenType* out_type, int32_t* out_value) const;
|
||||
const char* expr, ExpressionTokenType* out_type, int32_t* out_value) const;
|
||||
std::vector<std::shared_ptr<const Card>> get_targeted_cards_for_condition(
|
||||
uint16_t card_ref,
|
||||
uint8_t def_effect_index,
|
||||
@@ -341,6 +337,4 @@ private:
|
||||
uint16_t unknown_a2;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
+349
-362
@@ -8,18 +8,16 @@
|
||||
#include <phosg/Random.hh>
|
||||
#include <phosg/Time.hh>
|
||||
|
||||
#include "../Loggers.hh"
|
||||
#include "../Compression.hh"
|
||||
#include "../Loggers.hh"
|
||||
#include "../PSOEncryption.hh"
|
||||
#include "../Text.hh"
|
||||
#include "../Quest.hh"
|
||||
#include "../Text.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
const char* name_for_attack_medium(AttackMedium medium) {
|
||||
switch (medium) {
|
||||
case AttackMedium::UNKNOWN:
|
||||
@@ -37,12 +35,13 @@ const char* name_for_attack_medium(AttackMedium medium) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Location::Location() : Location(0, 0) { }
|
||||
Location::Location(uint8_t x, uint8_t y) : Location(x, y, Direction::RIGHT) { }
|
||||
Location::Location() : Location(0, 0) {}
|
||||
Location::Location(uint8_t x, uint8_t y) : Location(x, y, Direction::RIGHT) {}
|
||||
Location::Location(uint8_t x, uint8_t y, Direction direction)
|
||||
: x(x), y(y), direction(direction), unused(0) { }
|
||||
: x(x),
|
||||
y(y),
|
||||
direction(direction),
|
||||
unused(0) {}
|
||||
|
||||
bool Location::operator==(const Location& other) const {
|
||||
return (this->x == other.x) &&
|
||||
@@ -56,7 +55,7 @@ bool Location::operator!=(const Location& other) const {
|
||||
|
||||
std::string Location::str() const {
|
||||
return string_printf("Location[x=%hhu, y=%hhu, dir=%s, u=%hhu]",
|
||||
this->x, this->y, name_for_direction(this->direction), this->unused);
|
||||
this->x, this->y, name_for_direction(this->direction), this->unused);
|
||||
}
|
||||
|
||||
void Location::clear() {
|
||||
@@ -73,8 +72,6 @@ void Location::clear_FF() {
|
||||
this->unused = 0xFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Direction turn_left(Direction d) {
|
||||
switch (d) {
|
||||
case Direction::RIGHT:
|
||||
@@ -137,65 +134,61 @@ const char* name_for_direction(Direction d) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool card_class_is_tech_like(CardClass cc) {
|
||||
return (cc == CardClass::TECH) ||
|
||||
(cc == CardClass::PHOTON_BLAST) ||
|
||||
(cc == CardClass::BOSS_TECH);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const vector<const char*> name_for_card_type({
|
||||
"HunterSC",
|
||||
"ArkzSC",
|
||||
"Item",
|
||||
"Creature",
|
||||
"Action",
|
||||
"Assist",
|
||||
"HunterSC",
|
||||
"ArkzSC",
|
||||
"Item",
|
||||
"Creature",
|
||||
"Action",
|
||||
"Assist",
|
||||
});
|
||||
|
||||
static const unordered_map<string, const char*> description_for_expr_token({
|
||||
{"f", "Number of FCs controlled by current SC"},
|
||||
{"d", "Die roll"},
|
||||
{"ap", "Attacker effective AP"},
|
||||
{"tp", "Attacker effective TP"},
|
||||
{"hp", "Current HP"},
|
||||
{"mhp", "Maximum HP"},
|
||||
{"dm", "Physical damage"},
|
||||
{"tdm", "Technique damage"},
|
||||
{"tf", "Number of SC\'s destroyed FCs"},
|
||||
{"ac", "Remaining ATK points"},
|
||||
{"php", "Maximum HP"},
|
||||
{"dc", "Die roll"},
|
||||
{"cs", "Card set cost"},
|
||||
{"a", "Number of FCs on all teams"},
|
||||
{"kap", "Action cards AP"},
|
||||
{"ktp", "Action cards TP"},
|
||||
{"dn", "Unknown: dn"},
|
||||
{"hf", "Number of item or creature cards in hand"},
|
||||
{"df", "Number of destroyed ally FCs (including SC\'s own)"},
|
||||
{"ff", "Number of ally FCs (including SC\'s own)"},
|
||||
{"ef", "Number of enemy FCs"},
|
||||
{"bi", "Number of Native FCs on either team"},
|
||||
{"ab", "Number of A.Beast FCs on either team"},
|
||||
{"mc", "Number of Machine FCs on either team"},
|
||||
{"dk", "Number of Dark FCs on either team"},
|
||||
{"sa", "Number of Sword-type items on either team"},
|
||||
{"gn", "Number of Gun-type items on either team"},
|
||||
{"wd", "Number of Cane-type items on either team"},
|
||||
{"tt", "Physical damage"},
|
||||
{"lv", "Dice boost"},
|
||||
{"adm", "SC attack damage"},
|
||||
{"ddm", "Defending damage"},
|
||||
{"sat", "Number of Sword-type items on SC\'s team"},
|
||||
{"edm", "Defending damage"}, // TODO: How is this different from ddm?
|
||||
{"ldm", "Unknown: ldm"}, // Unused
|
||||
{"rdm", "Defending damage"}, // TODO: How is this different from ddm/edm?
|
||||
{"fdm", "Final damage (after defense)"},
|
||||
{"ndm", "Unknown: ndm"}, // Unused
|
||||
{"ehp", "Attacker HP"},
|
||||
{"f", "Number of FCs controlled by current SC"},
|
||||
{"d", "Die roll"},
|
||||
{"ap", "Attacker effective AP"},
|
||||
{"tp", "Attacker effective TP"},
|
||||
{"hp", "Current HP"},
|
||||
{"mhp", "Maximum HP"},
|
||||
{"dm", "Physical damage"},
|
||||
{"tdm", "Technique damage"},
|
||||
{"tf", "Number of SC\'s destroyed FCs"},
|
||||
{"ac", "Remaining ATK points"},
|
||||
{"php", "Maximum HP"},
|
||||
{"dc", "Die roll"},
|
||||
{"cs", "Card set cost"},
|
||||
{"a", "Number of FCs on all teams"},
|
||||
{"kap", "Action cards AP"},
|
||||
{"ktp", "Action cards TP"},
|
||||
{"dn", "Unknown: dn"},
|
||||
{"hf", "Number of item or creature cards in hand"},
|
||||
{"df", "Number of destroyed ally FCs (including SC\'s own)"},
|
||||
{"ff", "Number of ally FCs (including SC\'s own)"},
|
||||
{"ef", "Number of enemy FCs"},
|
||||
{"bi", "Number of Native FCs on either team"},
|
||||
{"ab", "Number of A.Beast FCs on either team"},
|
||||
{"mc", "Number of Machine FCs on either team"},
|
||||
{"dk", "Number of Dark FCs on either team"},
|
||||
{"sa", "Number of Sword-type items on either team"},
|
||||
{"gn", "Number of Gun-type items on either team"},
|
||||
{"wd", "Number of Cane-type items on either team"},
|
||||
{"tt", "Physical damage"},
|
||||
{"lv", "Dice boost"},
|
||||
{"adm", "SC attack damage"},
|
||||
{"ddm", "Defending damage"},
|
||||
{"sat", "Number of Sword-type items on SC\'s team"},
|
||||
{"edm", "Defending damage"}, // TODO: How is this different from ddm?
|
||||
{"ldm", "Unknown: ldm"}, // Unused
|
||||
{"rdm", "Defending damage"}, // TODO: How is this different from ddm/edm?
|
||||
{"fdm", "Final damage (after defense)"},
|
||||
{"ndm", "Unknown: ndm"}, // Unused
|
||||
{"ehp", "Attacker HP"},
|
||||
});
|
||||
|
||||
// Arguments are encoded as 3-character null-terminated strings (why?!), and are
|
||||
@@ -224,82 +217,82 @@ static const unordered_map<string, const char*> description_for_expr_token({
|
||||
// tXX = lasts XX turns, or activate after XX turns
|
||||
|
||||
static const vector<const char*> description_for_n_condition({
|
||||
/* n00 */ "Always true",
|
||||
/* n01 */ "Card is Hunters-side SC",
|
||||
/* n02 */ "Destroyed with a single attack",
|
||||
/* n03 */ "Technique or PB action card was used",
|
||||
/* n04 */ "Attack has Pierce",
|
||||
/* n05 */ "Attack has Rampage",
|
||||
/* n06 */ "Native attribute",
|
||||
/* n07 */ "A.Beast attribute",
|
||||
/* n08 */ "Machine attribute",
|
||||
/* n09 */ "Dark attribute",
|
||||
/* n10 */ "Sword-type item",
|
||||
/* n11 */ "Gun-type item",
|
||||
/* n12 */ "Cane-type item",
|
||||
/* n13 */ "Guard item or MAG",
|
||||
/* n14 */ "Story Character",
|
||||
/* n15 */ "Attacker does not use action cards",
|
||||
/* n16 */ "Aerial attribute",
|
||||
/* n17 */ "Same AP as opponent",
|
||||
/* n18 */ "Any target is an SC",
|
||||
/* n19 */ "Has Paralyzed condition",
|
||||
/* n20 */ "Has Frozen condition",
|
||||
/* n21 */ "???", // TODO: This appears related to Pierce/Rampage
|
||||
/* n22 */ "???", // TODO: This appears related to Pierce/Rampage
|
||||
/* n00 */ "Always true",
|
||||
/* n01 */ "Card is Hunters-side SC",
|
||||
/* n02 */ "Destroyed with a single attack",
|
||||
/* n03 */ "Technique or PB action card was used",
|
||||
/* n04 */ "Attack has Pierce",
|
||||
/* n05 */ "Attack has Rampage",
|
||||
/* n06 */ "Native attribute",
|
||||
/* n07 */ "A.Beast attribute",
|
||||
/* n08 */ "Machine attribute",
|
||||
/* n09 */ "Dark attribute",
|
||||
/* n10 */ "Sword-type item",
|
||||
/* n11 */ "Gun-type item",
|
||||
/* n12 */ "Cane-type item",
|
||||
/* n13 */ "Guard item or MAG",
|
||||
/* n14 */ "Story Character",
|
||||
/* n15 */ "Attacker does not use action cards",
|
||||
/* n16 */ "Aerial attribute",
|
||||
/* n17 */ "Same AP as opponent",
|
||||
/* n18 */ "Any target is an SC",
|
||||
/* n19 */ "Has Paralyzed condition",
|
||||
/* n20 */ "Has Frozen condition",
|
||||
/* n21 */ "???", // TODO: This appears related to Pierce/Rampage
|
||||
/* n22 */ "???", // TODO: This appears related to Pierce/Rampage
|
||||
});
|
||||
|
||||
static const vector<const char*> description_for_p_target({
|
||||
/* p00 */ "Unknown: p00", // Unused; probably invalid
|
||||
/* p01 */ "SC / FC who set the card",
|
||||
/* p02 */ "Attacking SC / FC",
|
||||
/* p03 */ "Unknown: p03", // Unused
|
||||
/* p04 */ "Unknown: p04", // Unused
|
||||
/* p05 */ "SC / FC who set the card", // Identical to p01
|
||||
/* p06 */ "??? (TODO)",
|
||||
/* p07 */ "??? (TODO; Weakness)",
|
||||
/* p08 */ "FC\'s owner SC",
|
||||
/* p09 */ "Unknown: p09", // Unused
|
||||
/* p10 */ "All ally FCs",
|
||||
/* p11 */ "All ally FCs", // TODO: how is this different from p10?
|
||||
/* p12 */ "All non-aerial FCs on both teams",
|
||||
/* p13 */ "All FCs on both teams that are Frozen",
|
||||
/* p14 */ "All FCs on both teams that have <= 3 HP",
|
||||
/* p15 */ "All FCs except SCs", // TODO: used during attacks only?
|
||||
/* p16 */ "All FCs except SCs", // TODO: used during attacks only? how is this different from p15?
|
||||
/* p17 */ "This card",
|
||||
/* p18 */ "SC who equipped this card",
|
||||
/* p19 */ "Unknown: p19", // Unused
|
||||
/* p20 */ "Unknown: p20", // Unused
|
||||
/* p21 */ "Unknown: p21", // Unused
|
||||
/* p22 */ "All characters (SCs & FCs) including this card", // TODO: But why does Shifta apply only to allies then?
|
||||
/* p23 */ "All characters (SCs & FCs) except this card",
|
||||
/* p24 */ "All FCs on both teams that have Paralysis",
|
||||
/* p25 */ "Unknown: p25", // Unused
|
||||
/* p26 */ "Unknown: p26", // Unused
|
||||
/* p27 */ "Unknown: p27", // Unused
|
||||
/* p28 */ "Unknown: p28", // Unused
|
||||
/* p29 */ "Unknown: p29", // Unused
|
||||
/* p30 */ "Unknown: p30", // Unused
|
||||
/* p31 */ "Unknown: p31", // Unused
|
||||
/* p32 */ "Unknown: p32", // Unused
|
||||
/* p33 */ "Unknown: p33", // Unused
|
||||
/* p34 */ "Unknown: p34", // Unused
|
||||
/* p35 */ "All characters (SCs & FCs) within range", // Used for Explosion effect
|
||||
/* p36 */ "All ally SCs within range, but not the caster", // Resta
|
||||
/* p37 */ "All FCs or all opponent FCs (TODO)", // TODO: when to use which selector? is a3 involved here somehow?
|
||||
/* p38 */ "All allies except items within range (and not this card)",
|
||||
/* p39 */ "All FCs that cost 4 or more points",
|
||||
/* p40 */ "All FCs that cost 3 or fewer points",
|
||||
/* p41 */ "Unknown: p41", // Unused
|
||||
/* p42 */ "Attacker during defense phase", // Only used by TP Defense
|
||||
/* p43 */ "Owner SC of defending FC during attack",
|
||||
/* p44 */ "SC\'s own creature FCs within range",
|
||||
/* p45 */ "Both attacker and defender", // Used for Snatch, which moves EXP from one to the other
|
||||
/* p46 */ "All SCs & FCs one space left or right of this card",
|
||||
/* p47 */ "FC\'s owner Boss SC", // Only used for Gibbles+ which explicitly mentions Boss SC, so it looks like this is p08 but for bosses
|
||||
/* p48 */ "Everything within range, including this card\'s user", // Madness
|
||||
/* p49 */ "All ally FCs within range except this card",
|
||||
/* p00 */ "Unknown: p00", // Unused; probably invalid
|
||||
/* p01 */ "SC / FC who set the card",
|
||||
/* p02 */ "Attacking SC / FC",
|
||||
/* p03 */ "Unknown: p03", // Unused
|
||||
/* p04 */ "Unknown: p04", // Unused
|
||||
/* p05 */ "SC / FC who set the card", // Identical to p01
|
||||
/* p06 */ "??? (TODO)",
|
||||
/* p07 */ "??? (TODO; Weakness)",
|
||||
/* p08 */ "FC\'s owner SC",
|
||||
/* p09 */ "Unknown: p09", // Unused
|
||||
/* p10 */ "All ally FCs",
|
||||
/* p11 */ "All ally FCs", // TODO: how is this different from p10?
|
||||
/* p12 */ "All non-aerial FCs on both teams",
|
||||
/* p13 */ "All FCs on both teams that are Frozen",
|
||||
/* p14 */ "All FCs on both teams that have <= 3 HP",
|
||||
/* p15 */ "All FCs except SCs", // TODO: used during attacks only?
|
||||
/* p16 */ "All FCs except SCs", // TODO: used during attacks only? how is this different from p15?
|
||||
/* p17 */ "This card",
|
||||
/* p18 */ "SC who equipped this card",
|
||||
/* p19 */ "Unknown: p19", // Unused
|
||||
/* p20 */ "Unknown: p20", // Unused
|
||||
/* p21 */ "Unknown: p21", // Unused
|
||||
/* p22 */ "All characters (SCs & FCs) including this card", // TODO: But why does Shifta apply only to allies then?
|
||||
/* p23 */ "All characters (SCs & FCs) except this card",
|
||||
/* p24 */ "All FCs on both teams that have Paralysis",
|
||||
/* p25 */ "Unknown: p25", // Unused
|
||||
/* p26 */ "Unknown: p26", // Unused
|
||||
/* p27 */ "Unknown: p27", // Unused
|
||||
/* p28 */ "Unknown: p28", // Unused
|
||||
/* p29 */ "Unknown: p29", // Unused
|
||||
/* p30 */ "Unknown: p30", // Unused
|
||||
/* p31 */ "Unknown: p31", // Unused
|
||||
/* p32 */ "Unknown: p32", // Unused
|
||||
/* p33 */ "Unknown: p33", // Unused
|
||||
/* p34 */ "Unknown: p34", // Unused
|
||||
/* p35 */ "All characters (SCs & FCs) within range", // Used for Explosion effect
|
||||
/* p36 */ "All ally SCs within range, but not the caster", // Resta
|
||||
/* p37 */ "All FCs or all opponent FCs (TODO)", // TODO: when to use which selector? is a3 involved here somehow?
|
||||
/* p38 */ "All allies except items within range (and not this card)",
|
||||
/* p39 */ "All FCs that cost 4 or more points",
|
||||
/* p40 */ "All FCs that cost 3 or fewer points",
|
||||
/* p41 */ "Unknown: p41", // Unused
|
||||
/* p42 */ "Attacker during defense phase", // Only used by TP Defense
|
||||
/* p43 */ "Owner SC of defending FC during attack",
|
||||
/* p44 */ "SC\'s own creature FCs within range",
|
||||
/* p45 */ "Both attacker and defender", // Used for Snatch, which moves EXP from one to the other
|
||||
/* p46 */ "All SCs & FCs one space left or right of this card",
|
||||
/* p47 */ "FC\'s owner Boss SC", // Only used for Gibbles+ which explicitly mentions Boss SC, so it looks like this is p08 but for bosses
|
||||
/* p48 */ "Everything within range, including this card\'s user", // Madness
|
||||
/* p49 */ "All ally FCs within range except this card",
|
||||
});
|
||||
|
||||
struct ConditionDescription {
|
||||
@@ -309,132 +302,132 @@ struct ConditionDescription {
|
||||
};
|
||||
|
||||
static const vector<ConditionDescription> description_for_condition_type({
|
||||
/* 0x00 */ {false, "NONE", nullptr},
|
||||
/* 0x01 */ {true, "AP_BOOST", "Temporarily increase AP by N"},
|
||||
/* 0x02 */ {false, "RAMPAGE", "Rampage"},
|
||||
/* 0x03 */ {true, "MULTI_STRIKE", "Duplicate attack N times"},
|
||||
/* 0x04 */ {true, "DAMAGE_MOD_1", "Set attack damage / AP to N after action cards applied (step 1)"},
|
||||
/* 0x05 */ {false, "IMMOBILE", "Give Immobile condition"},
|
||||
/* 0x06 */ {false, "HOLD", "Give Hold condition"},
|
||||
/* 0x07 */ {false, "UNKNOWN_07", nullptr},
|
||||
/* 0x08 */ {true, "TP_BOOST", "Add N TP temporarily during attack"},
|
||||
/* 0x09 */ {true, "GIVE_DAMAGE", "Cause direct N HP loss"},
|
||||
/* 0x0A */ {false, "GUOM", "Give Guom condition"},
|
||||
/* 0x0B */ {false, "PARALYZE", "Give Paralysis condition"},
|
||||
/* 0x0C */ {false, "UNKNOWN_0C", nullptr},
|
||||
/* 0x0D */ {false, "A_H_SWAP", "Swap AP and HP temporarily"},
|
||||
/* 0x0E */ {false, "PIERCE", "Attack SC directly even if they have items equipped"},
|
||||
/* 0x0F */ {false, "UNKNOWN_0F", nullptr},
|
||||
/* 0x10 */ {true, "HEAL", "Increase HP by N"},
|
||||
/* 0x11 */ {false, "RETURN_TO_HAND", "Return card to hand"},
|
||||
/* 0x12 */ {false, "UNKNOWN_12", nullptr},
|
||||
/* 0x13 */ {false, "UNKNOWN_13", nullptr},
|
||||
/* 0x14 */ {false, "ACID", "Give Acid condition"},
|
||||
/* 0x15 */ {false, "UNKNOWN_15", nullptr},
|
||||
/* 0x16 */ {true, "MIGHTY_KNUCKLE", "Temporarily increase AP by N, and set ATK dice to zero"},
|
||||
/* 0x17 */ {true, "UNIT_BLOW", "Temporarily increase AP by N * number of this card set within phase"},
|
||||
/* 0x18 */ {false, "CURSE", "Give Curse condition"},
|
||||
/* 0x19 */ {false, "COMBO_AP", "Temporarily increase AP by number of this card set within phase"},
|
||||
/* 0x1A */ {false, "PIERCE_RAMPAGE_BLOCK", "Block attack if Pierce/Rampage (?)"},
|
||||
/* 0x1B */ {false, "ABILITY_TRAP", "Temporarily disable opponent abilities"},
|
||||
/* 0x1C */ {false, "FREEZE", "Give Freeze condition"},
|
||||
/* 0x1D */ {false, "ANTI_ABNORMALITY_1", "Cure all conditions"},
|
||||
/* 0x1E */ {false, "UNKNOWN_1E", nullptr},
|
||||
/* 0x1F */ {false, "EXPLOSION", "Damage all SCs and FCs by number of this same card set * 2"},
|
||||
/* 0x20 */ {false, "UNKNOWN_20", nullptr},
|
||||
/* 0x21 */ {false, "UNKNOWN_21", nullptr},
|
||||
/* 0x22 */ {false, "UNKNOWN_22", nullptr},
|
||||
/* 0x23 */ {false, "RETURN_TO_DECK", "Cancel discard and move to bottom of deck instead"},
|
||||
/* 0x24 */ {false, "AERIAL", "Give Aerial status"},
|
||||
/* 0x25 */ {true, "AP_LOSS", "Make attacker temporarily lose N AP during defense"},
|
||||
/* 0x26 */ {true, "BONUS_FROM_LEADER", "Gain AP equal to the number of cards of type N on the field"},
|
||||
/* 0x27 */ {false, "FREE_MANEUVER", "Enable movement over occupied tiles"},
|
||||
/* 0x28 */ {false, "HASTE", "Make move actions free"},
|
||||
/* 0x29 */ {true, "CLONE", "Make setting this card free if at least one card of type N is already on the field"},
|
||||
/* 0x2A */ {true, "DEF_DISABLE_BY_COST", "Disable use of any defense cards costing between (N / 10) and (N % 10) points, inclusive"},
|
||||
/* 0x2B */ {true, "FILIAL", "Increase controlling SC\'s HP by N when this card is destroyed"},
|
||||
/* 0x2C */ {true, "SNATCH", "Steal N EXP during attack"},
|
||||
/* 0x2D */ {true, "HAND_DISRUPTER", "Discard N cards from hand immediately"},
|
||||
/* 0x2E */ {false, "DROP", "Give Drop condition"},
|
||||
/* 0x2F */ {false, "ACTION_DISRUPTER", "Destroy all action cards used by attacker"},
|
||||
/* 0x30 */ {true, "SET_HP", "Set HP to N"},
|
||||
/* 0x31 */ {false, "NATIVE_SHIELD", "Block attacks from Native creatures"},
|
||||
/* 0x32 */ {false, "A_BEAST_SHIELD", "Block attacks from A.Beast creatures"},
|
||||
/* 0x33 */ {false, "MACHINE_SHIELD", "Block attacks from Machine creatures"},
|
||||
/* 0x34 */ {false, "DARK_SHIELD", "Block attacks from Dark creatures"},
|
||||
/* 0x35 */ {false, "SWORD_SHIELD", "Block attacks from Sword items"},
|
||||
/* 0x36 */ {false, "GUN_SHIELD", "Block attacks from Gun items"},
|
||||
/* 0x37 */ {false, "CANE_SHIELD", "Block attacks from Cane items"},
|
||||
/* 0x38 */ {false, "UNKNOWN_38", nullptr},
|
||||
/* 0x39 */ {false, "UNKNOWN_39", nullptr},
|
||||
/* 0x3A */ {false, "DEFENDER", "Make attacks go to setter of this card instead of original target"},
|
||||
/* 0x3B */ {false, "SURVIVAL_DECOYS", "Redirect damage for multi-sided attack"},
|
||||
/* 0x3C */ {true, "GIVE_OR_TAKE_EXP", "Give N EXP, or take if N is negative"},
|
||||
/* 0x3D */ {false, "UNKNOWN_3D", nullptr},
|
||||
/* 0x3E */ {false, "DEATH_COMPANION", "If this card has 1 or 2 HP, set its HP to N"},
|
||||
/* 0x3F */ {true, "EXP_DECOY", "If defender has EXP, lose EXP instead of getting damage when attacked"},
|
||||
/* 0x40 */ {true, "SET_MV", "Set MV to N"},
|
||||
/* 0x41 */ {true, "GROUP", "Temporarily increase AP by N * number of this card on field, excluding itself"},
|
||||
/* 0x42 */ {false, "BERSERK", "User of this card receives the same damage as target, and isn\'t helped by target\'s defense cards"},
|
||||
/* 0x43 */ {false, "GUARD_CREATURE", "Attacks on controlling SC damage this card instead"},
|
||||
/* 0x44 */ {false, "TECH", "Technique cards cost 1 fewer ATK point"},
|
||||
/* 0x45 */ {false, "BIG_SWING", "Increase all attacking ATK costs by 1"},
|
||||
/* 0x46 */ {false, "UNKNOWN_46", nullptr},
|
||||
/* 0x47 */ {false, "SHIELD_WEAPON", "Limit attacker\'s choice of target to guard items"},
|
||||
/* 0x48 */ {false, "ATK_DICE_BOOST", "Increase ATK dice roll by 1"},
|
||||
/* 0x49 */ {false, "UNKNOWN_49", nullptr},
|
||||
/* 0x4A */ {false, "MAJOR_PIERCE", "If SC has over half of max HP, attacks target SC instead of equipped items"},
|
||||
/* 0x4B */ {false, "HEAVY_PIERCE", "If SC has 3 or more items equipped, attacks target SC instead of equipped items"},
|
||||
/* 0x4C */ {false, "MAJOR_RAMPAGE", "If SC has over half of max HP, attacks target SC and all equipped items"},
|
||||
/* 0x4D */ {false, "HEAVY_RAMPAGE", "If SC has 3 or more items equipped, attacks target SC and all equipped items"},
|
||||
/* 0x4E */ {true, "AP_GROWTH", "Permanently increase AP by N"},
|
||||
/* 0x4F */ {true, "TP_GROWTH", "Permanently increase TP by N"},
|
||||
/* 0x50 */ {true, "REBORN", "If any card of type N is on the field, this card goes to the hand when destroyed instead of being discarded"},
|
||||
/* 0x51 */ {true, "COPY", "Temporarily set AP/TP to N percent (or 100% if N is 0) of opponent\'s values"},
|
||||
/* 0x52 */ {false, "UNKNOWN_52", nullptr},
|
||||
/* 0x53 */ {true, "MISC_GUARDS", "Add N to card\'s defense value"},
|
||||
/* 0x54 */ {true, "AP_OVERRIDE", "Set AP to N temporarily"},
|
||||
/* 0x55 */ {true, "TP_OVERRIDE", "Set TP to N temporarily"},
|
||||
/* 0x56 */ {false, "RETURN", "Return card to hand on destruction instead of discarding"},
|
||||
/* 0x57 */ {false, "A_T_SWAP_PERM", "Permanently swap AP and TP"},
|
||||
/* 0x58 */ {false, "A_H_SWAP_PERM", "Permanently swap AP and HP"},
|
||||
/* 0x59 */ {true, "SLAYERS_ASSASSINS", "Temporarily increase AP during attack"},
|
||||
/* 0x5A */ {false, "ANTI_ABNORMALITY_2", "Remove all conditions"},
|
||||
/* 0x5B */ {false, "FIXED_RANGE", "Use SC\'s range instead of weapon or attack card ranges"},
|
||||
/* 0x5C */ {false, "ELUDE", "SC does not lose HP when equipped items are destroyed"},
|
||||
/* 0x5D */ {false, "PARRY", "Forward attack to a random FC within one tile of original target, excluding attacker and original target"},
|
||||
/* 0x5E */ {false, "BLOCK_ATTACK", "Completely block attack"},
|
||||
/* 0x5F */ {false, "UNKNOWN_5F", nullptr},
|
||||
/* 0x60 */ {false, "UNKNOWN_60", nullptr},
|
||||
/* 0x61 */ {true, "COMBO_TP", "Gain TP equal to the number of cards of type N on the field"},
|
||||
/* 0x62 */ {true, "MISC_AP_BONUSES", "Temporarily increase AP by N"},
|
||||
/* 0x63 */ {true, "MISC_TP_BONUSES", "Temporarily increase TP by N"},
|
||||
/* 0x64 */ {false, "UNKNOWN_64", nullptr},
|
||||
/* 0x65 */ {true, "MISC_DEFENSE_BONUSES", "Decrease damage by N"},
|
||||
/* 0x66 */ {true, "MOSTLY_HALFGUARDS", "Reduce damage from incoming attack by N"},
|
||||
/* 0x67 */ {false, "PERIODIC_FIELD", "Swap immunity to tech or physical attacks"},
|
||||
/* 0x68 */ {false, "FC_LIMIT_BY_COUNT", "Change FC limit from 8 ATK points total to 4 FCs total"},
|
||||
/* 0x69 */ {false, "UNKNOWN_69", nullptr},
|
||||
/* 0x6A */ {true, "MV_BONUS", "Increase MV by N"},
|
||||
/* 0x6B */ {true, "FORWARD_DAMAGE", "Give N damage back to attacker during defense (?) (TODO)"},
|
||||
/* 0x6C */ {true, "WEAK_SPOT_INFLUENCE", "Temporarily decrease AP by N"},
|
||||
/* 0x6D */ {true, "DAMAGE_MODIFIER_2", "Set attack damage / AP after action cards applied (step 2)"},
|
||||
/* 0x6E */ {true, "WEAK_HIT_BLOCK", "Block all attacks of N damage or less"},
|
||||
/* 0x6F */ {true, "AP_SILENCE", "Temporarily decrease AP of opponent by N"},
|
||||
/* 0x70 */ {true, "TP_SILENCE", "Temporarily decrease TP of opponent by N"},
|
||||
/* 0x71 */ {false, "A_T_SWAP", "Temporarily swap AP and TP"},
|
||||
/* 0x72 */ {true, "HALFGUARD", "Halve damage from attacks that would inflict N or more damage"},
|
||||
/* 0x73 */ {false, "UNKNOWN_73", nullptr},
|
||||
/* 0x74 */ {true, "RAMPAGE_AP_LOSS", "Temporarily reduce AP by N"},
|
||||
/* 0x75 */ {false, "UNKNOWN_75", nullptr},
|
||||
/* 0x76 */ {false, "REFLECT", "Generate reverse attack"},
|
||||
/* 0x77 */ {false, "UNKNOWN_77", nullptr},
|
||||
/* 0x78 */ {false, "ANY", nullptr}, // Treated as "any condition" in find functions
|
||||
/* 0x79 */ {false, "UNKNOWN_79", nullptr},
|
||||
/* 0x7A */ {false, "UNKNOWN_7A", nullptr},
|
||||
/* 0x7B */ {false, "UNKNOWN_7B", nullptr},
|
||||
/* 0x7C */ {false, "UNKNOWN_7C", nullptr},
|
||||
/* 0x7D */ {false, "UNKNOWN_7D", nullptr},
|
||||
/* 0x00 */ {false, "NONE", nullptr},
|
||||
/* 0x01 */ {true, "AP_BOOST", "Temporarily increase AP by N"},
|
||||
/* 0x02 */ {false, "RAMPAGE", "Rampage"},
|
||||
/* 0x03 */ {true, "MULTI_STRIKE", "Duplicate attack N times"},
|
||||
/* 0x04 */ {true, "DAMAGE_MOD_1", "Set attack damage / AP to N after action cards applied (step 1)"},
|
||||
/* 0x05 */ {false, "IMMOBILE", "Give Immobile condition"},
|
||||
/* 0x06 */ {false, "HOLD", "Give Hold condition"},
|
||||
/* 0x07 */ {false, "UNKNOWN_07", nullptr},
|
||||
/* 0x08 */ {true, "TP_BOOST", "Add N TP temporarily during attack"},
|
||||
/* 0x09 */ {true, "GIVE_DAMAGE", "Cause direct N HP loss"},
|
||||
/* 0x0A */ {false, "GUOM", "Give Guom condition"},
|
||||
/* 0x0B */ {false, "PARALYZE", "Give Paralysis condition"},
|
||||
/* 0x0C */ {false, "UNKNOWN_0C", nullptr},
|
||||
/* 0x0D */ {false, "A_H_SWAP", "Swap AP and HP temporarily"},
|
||||
/* 0x0E */ {false, "PIERCE", "Attack SC directly even if they have items equipped"},
|
||||
/* 0x0F */ {false, "UNKNOWN_0F", nullptr},
|
||||
/* 0x10 */ {true, "HEAL", "Increase HP by N"},
|
||||
/* 0x11 */ {false, "RETURN_TO_HAND", "Return card to hand"},
|
||||
/* 0x12 */ {false, "UNKNOWN_12", nullptr},
|
||||
/* 0x13 */ {false, "UNKNOWN_13", nullptr},
|
||||
/* 0x14 */ {false, "ACID", "Give Acid condition"},
|
||||
/* 0x15 */ {false, "UNKNOWN_15", nullptr},
|
||||
/* 0x16 */ {true, "MIGHTY_KNUCKLE", "Temporarily increase AP by N, and set ATK dice to zero"},
|
||||
/* 0x17 */ {true, "UNIT_BLOW", "Temporarily increase AP by N * number of this card set within phase"},
|
||||
/* 0x18 */ {false, "CURSE", "Give Curse condition"},
|
||||
/* 0x19 */ {false, "COMBO_AP", "Temporarily increase AP by number of this card set within phase"},
|
||||
/* 0x1A */ {false, "PIERCE_RAMPAGE_BLOCK", "Block attack if Pierce/Rampage (?)"},
|
||||
/* 0x1B */ {false, "ABILITY_TRAP", "Temporarily disable opponent abilities"},
|
||||
/* 0x1C */ {false, "FREEZE", "Give Freeze condition"},
|
||||
/* 0x1D */ {false, "ANTI_ABNORMALITY_1", "Cure all conditions"},
|
||||
/* 0x1E */ {false, "UNKNOWN_1E", nullptr},
|
||||
/* 0x1F */ {false, "EXPLOSION", "Damage all SCs and FCs by number of this same card set * 2"},
|
||||
/* 0x20 */ {false, "UNKNOWN_20", nullptr},
|
||||
/* 0x21 */ {false, "UNKNOWN_21", nullptr},
|
||||
/* 0x22 */ {false, "UNKNOWN_22", nullptr},
|
||||
/* 0x23 */ {false, "RETURN_TO_DECK", "Cancel discard and move to bottom of deck instead"},
|
||||
/* 0x24 */ {false, "AERIAL", "Give Aerial status"},
|
||||
/* 0x25 */ {true, "AP_LOSS", "Make attacker temporarily lose N AP during defense"},
|
||||
/* 0x26 */ {true, "BONUS_FROM_LEADER", "Gain AP equal to the number of cards of type N on the field"},
|
||||
/* 0x27 */ {false, "FREE_MANEUVER", "Enable movement over occupied tiles"},
|
||||
/* 0x28 */ {false, "HASTE", "Make move actions free"},
|
||||
/* 0x29 */ {true, "CLONE", "Make setting this card free if at least one card of type N is already on the field"},
|
||||
/* 0x2A */ {true, "DEF_DISABLE_BY_COST", "Disable use of any defense cards costing between (N / 10) and (N % 10) points, inclusive"},
|
||||
/* 0x2B */ {true, "FILIAL", "Increase controlling SC\'s HP by N when this card is destroyed"},
|
||||
/* 0x2C */ {true, "SNATCH", "Steal N EXP during attack"},
|
||||
/* 0x2D */ {true, "HAND_DISRUPTER", "Discard N cards from hand immediately"},
|
||||
/* 0x2E */ {false, "DROP", "Give Drop condition"},
|
||||
/* 0x2F */ {false, "ACTION_DISRUPTER", "Destroy all action cards used by attacker"},
|
||||
/* 0x30 */ {true, "SET_HP", "Set HP to N"},
|
||||
/* 0x31 */ {false, "NATIVE_SHIELD", "Block attacks from Native creatures"},
|
||||
/* 0x32 */ {false, "A_BEAST_SHIELD", "Block attacks from A.Beast creatures"},
|
||||
/* 0x33 */ {false, "MACHINE_SHIELD", "Block attacks from Machine creatures"},
|
||||
/* 0x34 */ {false, "DARK_SHIELD", "Block attacks from Dark creatures"},
|
||||
/* 0x35 */ {false, "SWORD_SHIELD", "Block attacks from Sword items"},
|
||||
/* 0x36 */ {false, "GUN_SHIELD", "Block attacks from Gun items"},
|
||||
/* 0x37 */ {false, "CANE_SHIELD", "Block attacks from Cane items"},
|
||||
/* 0x38 */ {false, "UNKNOWN_38", nullptr},
|
||||
/* 0x39 */ {false, "UNKNOWN_39", nullptr},
|
||||
/* 0x3A */ {false, "DEFENDER", "Make attacks go to setter of this card instead of original target"},
|
||||
/* 0x3B */ {false, "SURVIVAL_DECOYS", "Redirect damage for multi-sided attack"},
|
||||
/* 0x3C */ {true, "GIVE_OR_TAKE_EXP", "Give N EXP, or take if N is negative"},
|
||||
/* 0x3D */ {false, "UNKNOWN_3D", nullptr},
|
||||
/* 0x3E */ {false, "DEATH_COMPANION", "If this card has 1 or 2 HP, set its HP to N"},
|
||||
/* 0x3F */ {true, "EXP_DECOY", "If defender has EXP, lose EXP instead of getting damage when attacked"},
|
||||
/* 0x40 */ {true, "SET_MV", "Set MV to N"},
|
||||
/* 0x41 */ {true, "GROUP", "Temporarily increase AP by N * number of this card on field, excluding itself"},
|
||||
/* 0x42 */ {false, "BERSERK", "User of this card receives the same damage as target, and isn\'t helped by target\'s defense cards"},
|
||||
/* 0x43 */ {false, "GUARD_CREATURE", "Attacks on controlling SC damage this card instead"},
|
||||
/* 0x44 */ {false, "TECH", "Technique cards cost 1 fewer ATK point"},
|
||||
/* 0x45 */ {false, "BIG_SWING", "Increase all attacking ATK costs by 1"},
|
||||
/* 0x46 */ {false, "UNKNOWN_46", nullptr},
|
||||
/* 0x47 */ {false, "SHIELD_WEAPON", "Limit attacker\'s choice of target to guard items"},
|
||||
/* 0x48 */ {false, "ATK_DICE_BOOST", "Increase ATK dice roll by 1"},
|
||||
/* 0x49 */ {false, "UNKNOWN_49", nullptr},
|
||||
/* 0x4A */ {false, "MAJOR_PIERCE", "If SC has over half of max HP, attacks target SC instead of equipped items"},
|
||||
/* 0x4B */ {false, "HEAVY_PIERCE", "If SC has 3 or more items equipped, attacks target SC instead of equipped items"},
|
||||
/* 0x4C */ {false, "MAJOR_RAMPAGE", "If SC has over half of max HP, attacks target SC and all equipped items"},
|
||||
/* 0x4D */ {false, "HEAVY_RAMPAGE", "If SC has 3 or more items equipped, attacks target SC and all equipped items"},
|
||||
/* 0x4E */ {true, "AP_GROWTH", "Permanently increase AP by N"},
|
||||
/* 0x4F */ {true, "TP_GROWTH", "Permanently increase TP by N"},
|
||||
/* 0x50 */ {true, "REBORN", "If any card of type N is on the field, this card goes to the hand when destroyed instead of being discarded"},
|
||||
/* 0x51 */ {true, "COPY", "Temporarily set AP/TP to N percent (or 100% if N is 0) of opponent\'s values"},
|
||||
/* 0x52 */ {false, "UNKNOWN_52", nullptr},
|
||||
/* 0x53 */ {true, "MISC_GUARDS", "Add N to card\'s defense value"},
|
||||
/* 0x54 */ {true, "AP_OVERRIDE", "Set AP to N temporarily"},
|
||||
/* 0x55 */ {true, "TP_OVERRIDE", "Set TP to N temporarily"},
|
||||
/* 0x56 */ {false, "RETURN", "Return card to hand on destruction instead of discarding"},
|
||||
/* 0x57 */ {false, "A_T_SWAP_PERM", "Permanently swap AP and TP"},
|
||||
/* 0x58 */ {false, "A_H_SWAP_PERM", "Permanently swap AP and HP"},
|
||||
/* 0x59 */ {true, "SLAYERS_ASSASSINS", "Temporarily increase AP during attack"},
|
||||
/* 0x5A */ {false, "ANTI_ABNORMALITY_2", "Remove all conditions"},
|
||||
/* 0x5B */ {false, "FIXED_RANGE", "Use SC\'s range instead of weapon or attack card ranges"},
|
||||
/* 0x5C */ {false, "ELUDE", "SC does not lose HP when equipped items are destroyed"},
|
||||
/* 0x5D */ {false, "PARRY", "Forward attack to a random FC within one tile of original target, excluding attacker and original target"},
|
||||
/* 0x5E */ {false, "BLOCK_ATTACK", "Completely block attack"},
|
||||
/* 0x5F */ {false, "UNKNOWN_5F", nullptr},
|
||||
/* 0x60 */ {false, "UNKNOWN_60", nullptr},
|
||||
/* 0x61 */ {true, "COMBO_TP", "Gain TP equal to the number of cards of type N on the field"},
|
||||
/* 0x62 */ {true, "MISC_AP_BONUSES", "Temporarily increase AP by N"},
|
||||
/* 0x63 */ {true, "MISC_TP_BONUSES", "Temporarily increase TP by N"},
|
||||
/* 0x64 */ {false, "UNKNOWN_64", nullptr},
|
||||
/* 0x65 */ {true, "MISC_DEFENSE_BONUSES", "Decrease damage by N"},
|
||||
/* 0x66 */ {true, "MOSTLY_HALFGUARDS", "Reduce damage from incoming attack by N"},
|
||||
/* 0x67 */ {false, "PERIODIC_FIELD", "Swap immunity to tech or physical attacks"},
|
||||
/* 0x68 */ {false, "FC_LIMIT_BY_COUNT", "Change FC limit from 8 ATK points total to 4 FCs total"},
|
||||
/* 0x69 */ {false, "UNKNOWN_69", nullptr},
|
||||
/* 0x6A */ {true, "MV_BONUS", "Increase MV by N"},
|
||||
/* 0x6B */ {true, "FORWARD_DAMAGE", "Give N damage back to attacker during defense (?) (TODO)"},
|
||||
/* 0x6C */ {true, "WEAK_SPOT_INFLUENCE", "Temporarily decrease AP by N"},
|
||||
/* 0x6D */ {true, "DAMAGE_MODIFIER_2", "Set attack damage / AP after action cards applied (step 2)"},
|
||||
/* 0x6E */ {true, "WEAK_HIT_BLOCK", "Block all attacks of N damage or less"},
|
||||
/* 0x6F */ {true, "AP_SILENCE", "Temporarily decrease AP of opponent by N"},
|
||||
/* 0x70 */ {true, "TP_SILENCE", "Temporarily decrease TP of opponent by N"},
|
||||
/* 0x71 */ {false, "A_T_SWAP", "Temporarily swap AP and TP"},
|
||||
/* 0x72 */ {true, "HALFGUARD", "Halve damage from attacks that would inflict N or more damage"},
|
||||
/* 0x73 */ {false, "UNKNOWN_73", nullptr},
|
||||
/* 0x74 */ {true, "RAMPAGE_AP_LOSS", "Temporarily reduce AP by N"},
|
||||
/* 0x75 */ {false, "UNKNOWN_75", nullptr},
|
||||
/* 0x76 */ {false, "REFLECT", "Generate reverse attack"},
|
||||
/* 0x77 */ {false, "UNKNOWN_77", nullptr},
|
||||
/* 0x78 */ {false, "ANY", nullptr}, // Treated as "any condition" in find functions
|
||||
/* 0x79 */ {false, "UNKNOWN_79", nullptr},
|
||||
/* 0x7A */ {false, "UNKNOWN_7A", nullptr},
|
||||
/* 0x7B */ {false, "UNKNOWN_7B", nullptr},
|
||||
/* 0x7C */ {false, "UNKNOWN_7C", nullptr},
|
||||
/* 0x7D */ {false, "UNKNOWN_7D", nullptr},
|
||||
});
|
||||
|
||||
const char* name_for_condition_type(ConditionType cond_type) {
|
||||
@@ -445,8 +438,6 @@ const char* name_for_condition_type(ConditionType cond_type) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char* name_for_action_subphase(ActionSubphase subphase) {
|
||||
switch (subphase) {
|
||||
case ActionSubphase::ATTACK:
|
||||
@@ -460,8 +451,6 @@ const char* name_for_action_subphase(ActionSubphase subphase) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CardDefinition::Stat::decode_code() {
|
||||
this->type = static_cast<Type>(this->code / 1000);
|
||||
int16_t value = this->code - (this->type * 1000);
|
||||
@@ -512,8 +501,6 @@ string CardDefinition::Stat::str() const {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CardDefinition::Effect::is_empty() const {
|
||||
return (this->effect_num == 0 &&
|
||||
this->type == ConditionType::NONE &&
|
||||
@@ -588,7 +575,8 @@ string CardDefinition::Effect::str() const {
|
||||
cmd_str += ':';
|
||||
cmd_str += name;
|
||||
}
|
||||
} catch (const out_of_range&) { }
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
|
||||
string expr_str = this->expr;
|
||||
if (!expr_str.empty()) {
|
||||
@@ -599,12 +587,10 @@ string CardDefinition::Effect::str() const {
|
||||
string arg2str = this->str_for_arg(this->arg2);
|
||||
string arg3str = this->str_for_arg(this->arg3);
|
||||
return string_printf("(cmd=%s%s, when=%02hhX, arg1=%s, arg2=%s, arg3=%s, cond=%02hhX, a2=%02hhX)",
|
||||
cmd_str.c_str(), expr_str.c_str(), this->when, arg1str.data(),
|
||||
arg2str.data(), arg3str.data(), static_cast<uint8_t>(this->apply_criterion), this->unknown_a2);
|
||||
cmd_str.c_str(), expr_str.c_str(), this->when, arg1str.data(),
|
||||
arg2str.data(), arg3str.data(), static_cast<uint8_t>(this->apply_criterion), this->unknown_a2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CardDefinition::is_sc() const {
|
||||
return (this->type == CardType::HUNTERS_SC) || (this->type == CardType::ARKZ_SC);
|
||||
}
|
||||
@@ -614,8 +600,7 @@ bool CardDefinition::is_fc() const {
|
||||
}
|
||||
|
||||
bool CardDefinition::is_named_android_sc() const {
|
||||
static const unordered_set<uint16_t> TARGET_IDS({
|
||||
0x0005, 0x0007, 0x0110, 0x0113, 0x0114, 0x0117, 0x011B, 0x011F});
|
||||
static const unordered_set<uint16_t> TARGET_IDS({0x0005, 0x0007, 0x0110, 0x0113, 0x0114, 0x0117, 0x011B, 0x011F});
|
||||
return TARGET_IDS.count(this->card_id);
|
||||
}
|
||||
|
||||
@@ -636,8 +621,6 @@ CardClass CardDefinition::card_class() const {
|
||||
return static_cast<CardClass>(this->be_card_class.load());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CardDefinition::decode_range() {
|
||||
// If the cell representing the FC is nonzero, the card has a range from a
|
||||
// list of constants. Otherwise, its range is already defined in the range
|
||||
@@ -695,20 +678,20 @@ void CardDefinition::decode_range() {
|
||||
|
||||
string name_for_rarity(CardRarity rarity) {
|
||||
static const vector<const char*> names({
|
||||
"N1",
|
||||
"R1",
|
||||
"S",
|
||||
"E",
|
||||
"N2",
|
||||
"N3",
|
||||
"N4",
|
||||
"R2",
|
||||
"R3",
|
||||
"R4",
|
||||
"SS",
|
||||
"D1",
|
||||
"D2",
|
||||
"INVIS",
|
||||
"N1",
|
||||
"R1",
|
||||
"S",
|
||||
"E",
|
||||
"N2",
|
||||
"N3",
|
||||
"N4",
|
||||
"R2",
|
||||
"R3",
|
||||
"R4",
|
||||
"SS",
|
||||
"D1",
|
||||
"D2",
|
||||
"INVIS",
|
||||
});
|
||||
try {
|
||||
return names.at(static_cast<uint8_t>(rarity) - 1);
|
||||
@@ -719,16 +702,16 @@ string name_for_rarity(CardRarity rarity) {
|
||||
|
||||
string name_for_target_mode(TargetMode target_mode) {
|
||||
static const vector<const char*> names({
|
||||
"NONE",
|
||||
"SINGLE",
|
||||
"MULTI",
|
||||
"SELF",
|
||||
"TEAM",
|
||||
"ALL",
|
||||
"MULTI-ALLY",
|
||||
"ALL-ALLY",
|
||||
"ALL-ATTACK",
|
||||
"OWN-FCS",
|
||||
"NONE",
|
||||
"SINGLE",
|
||||
"MULTI",
|
||||
"SELF",
|
||||
"TEAM",
|
||||
"ALL",
|
||||
"MULTI-ALLY",
|
||||
"ALL-ALLY",
|
||||
"ALL-ATTACK",
|
||||
"OWN-FCS",
|
||||
});
|
||||
try {
|
||||
return names.at(static_cast<uint8_t>(target_mode));
|
||||
@@ -837,8 +820,6 @@ string CardDefinition::str() const {
|
||||
effects_str.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
Rules::Rules() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -920,7 +901,7 @@ string Rules::str() const {
|
||||
break;
|
||||
default:
|
||||
tokens.emplace_back(string_printf("hp_type=(%02hhX)",
|
||||
static_cast<uint8_t>(this->hp_type)));
|
||||
static_cast<uint8_t>(this->hp_type)));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -938,7 +919,7 @@ string Rules::str() const {
|
||||
break;
|
||||
default:
|
||||
tokens.emplace_back(string_printf("dice_exchange=(%02hhX)",
|
||||
static_cast<uint8_t>(this->dice_exchange_mode)));
|
||||
static_cast<uint8_t>(this->dice_exchange_mode)));
|
||||
break;
|
||||
}
|
||||
tokens.emplace_back(string_printf("dice_boost=%s", this->disable_dice_boost ? "DISABLED" : "ENABLED"));
|
||||
@@ -961,7 +942,7 @@ string Rules::str() const {
|
||||
break;
|
||||
default:
|
||||
tokens.emplace_back(string_printf("allowed_cards=(%02hhX)",
|
||||
static_cast<uint8_t>(this->allowed_cards)));
|
||||
static_cast<uint8_t>(this->allowed_cards)));
|
||||
break;
|
||||
}
|
||||
tokens.emplace_back(string_printf("assist_cards=%s", this->no_assist_cards ? "DISALLOWED" : "ALLOWED"));
|
||||
@@ -974,8 +955,6 @@ string Rules::str() const {
|
||||
return "Rules[" + join(tokens, ", ") + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
StateFlags::StateFlags() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -1028,8 +1007,6 @@ void StateFlags::clear_FF() {
|
||||
this->client_sc_card_types.clear(CardType::INVALID_FF);
|
||||
}
|
||||
|
||||
|
||||
|
||||
string MapDefinition::str(const DataIndex* data_index) const {
|
||||
deque<string> lines;
|
||||
auto add_map = [&](const parray<parray<uint8_t, 0x10>, 0x10>& tiles) {
|
||||
@@ -1043,13 +1020,14 @@ string MapDefinition::str(const DataIndex* data_index) const {
|
||||
};
|
||||
|
||||
lines.emplace_back(string_printf("Map %08" PRIX32 ": %hhux%hhu",
|
||||
this->map_number.load(), this->width, this->height));
|
||||
this->map_number.load(), this->width, this->height));
|
||||
lines.emplace_back(string_printf(" a1=%08" PRIX32, this->unknown_a1.load()));
|
||||
lines.emplace_back(string_printf(" environment_number=%02hhX", this->environment_number));
|
||||
lines.emplace_back(string_printf(" num_alt_maps=%02hhX", this->num_alt_maps));
|
||||
lines.emplace_back(" tiles:");
|
||||
add_map(this->map_tiles);
|
||||
lines.emplace_back(string_printf(" start_tile_definitions=[1p=%02hhX 2p=%02hhX,%02hhX 3p=%02hhX,%02hhX,%02hhX], [1p=%02hhX 2p=%02hhX,%02hhX 3p=%02hhX,%02hhX,%02hhX]",
|
||||
lines.emplace_back(string_printf(
|
||||
" start_tile_definitions=[1p=%02hhX 2p=%02hhX,%02hhX 3p=%02hhX,%02hhX,%02hhX], [1p=%02hhX 2p=%02hhX,%02hhX 3p=%02hhX,%02hhX,%02hhX]",
|
||||
this->start_tile_definitions[0][0], this->start_tile_definitions[0][1],
|
||||
this->start_tile_definitions[0][2], this->start_tile_definitions[0][3],
|
||||
this->start_tile_definitions[0][4], this->start_tile_definitions[0][5],
|
||||
@@ -1062,7 +1040,8 @@ string MapDefinition::str(const DataIndex* data_index) const {
|
||||
add_map(this->alt_maps1[w][z]);
|
||||
}
|
||||
for (size_t w = 0; w < 2; w++) {
|
||||
lines.emplace_back(string_printf(" alt tiles a3 %zu/%zu=%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g", z, w,
|
||||
lines.emplace_back(string_printf(
|
||||
" alt tiles a3 %zu/%zu=%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g", z, w,
|
||||
this->alt_maps_unknown_a3[w][z][0x00].load(), this->alt_maps_unknown_a3[w][z][0x01].load(),
|
||||
this->alt_maps_unknown_a3[w][z][0x02].load(), this->alt_maps_unknown_a3[w][z][0x03].load(),
|
||||
this->alt_maps_unknown_a3[w][z][0x04].load(), this->alt_maps_unknown_a3[w][z][0x05].load(),
|
||||
@@ -1076,7 +1055,8 @@ string MapDefinition::str(const DataIndex* data_index) const {
|
||||
}
|
||||
for (size_t w = 0; w < 3; w++) {
|
||||
for (size_t z = 0; z < 0x24; z += 3) {
|
||||
lines.emplace_back(string_printf(" a4[%zu][0x%02zX:0x%02zX]=%g %g %g", w, z, z + 3,
|
||||
lines.emplace_back(string_printf(
|
||||
" a4[%zu][0x%02zX:0x%02zX]=%g %g %g", w, z, z + 3,
|
||||
this->unknown_a4[w][z + 0].load(),
|
||||
this->unknown_a4[w][z + 1].load(),
|
||||
this->unknown_a4[w][z + 2].load()));
|
||||
@@ -1085,16 +1065,19 @@ string MapDefinition::str(const DataIndex* data_index) const {
|
||||
lines.emplace_back(" modification tiles:");
|
||||
add_map(this->modification_tiles);
|
||||
for (size_t z = 0; z < 0x70; z += 0x10) {
|
||||
lines.emplace_back(string_printf(" a5[0x%02zX:0x%02zX]=%02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX", z, z + 0x10,
|
||||
lines.emplace_back(string_printf(
|
||||
" a5[0x%02zX:0x%02zX]=%02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX", z, z + 0x10,
|
||||
this->unknown_a5[z + 0x00], this->unknown_a5[z + 0x01], this->unknown_a5[z + 0x02], this->unknown_a5[z + 0x03],
|
||||
this->unknown_a5[z + 0x04], this->unknown_a5[z + 0x05], this->unknown_a5[z + 0x06], this->unknown_a5[z + 0x07],
|
||||
this->unknown_a5[z + 0x08], this->unknown_a5[z + 0x09], this->unknown_a5[z + 0x0A], this->unknown_a5[z + 0x0B],
|
||||
this->unknown_a5[z + 0x0C], this->unknown_a5[z + 0x0D], this->unknown_a5[z + 0x0E], this->unknown_a5[z + 0x0F]));
|
||||
}
|
||||
lines.emplace_back(string_printf(" a5[0x70:0x74]=%02hhX %02hhX %02hhX %02hhX",
|
||||
lines.emplace_back(string_printf(
|
||||
" a5[0x70:0x74]=%02hhX %02hhX %02hhX %02hhX",
|
||||
this->unknown_a5[0x70], this->unknown_a5[0x71], this->unknown_a5[0x72], this->unknown_a5[0x73]));
|
||||
lines.emplace_back(" default_rules: " + this->default_rules.str());
|
||||
lines.emplace_back(string_printf(" a6=%02hhX %02hhX %02hhX %02hhX",
|
||||
lines.emplace_back(string_printf(
|
||||
" a6=%02hhX %02hhX %02hhX %02hhX",
|
||||
this->unknown_a6[0], this->unknown_a6[1], this->unknown_a6[2], this->unknown_a6[3]));
|
||||
lines.emplace_back(" name: " + string(this->name));
|
||||
lines.emplace_back(" location_name: " + string(this->location_name));
|
||||
@@ -1103,21 +1086,25 @@ string MapDefinition::str(const DataIndex* data_index) const {
|
||||
lines.emplace_back(string_printf(" map_xy: %hu %hu", this->map_x.load(), this->map_y.load()));
|
||||
for (size_t z = 0; z < 3; z++) {
|
||||
lines.emplace_back(string_printf(" npc_chars[%zu]:", z));
|
||||
lines.emplace_back(string_printf(" a1=%04hX %04hX",
|
||||
lines.emplace_back(string_printf(
|
||||
" a1=%04hX %04hX",
|
||||
this->npc_chars[z].unknown_a1[0].load(), this->npc_chars[z].unknown_a1[1].load()));
|
||||
lines.emplace_back(string_printf(" a2=%02hX %02hX %02hX %02hX",
|
||||
lines.emplace_back(string_printf(
|
||||
" a2=%02hX %02hX %02hX %02hX",
|
||||
this->npc_chars[z].unknown_a2[0], this->npc_chars[z].unknown_a2[1],
|
||||
this->npc_chars[z].unknown_a2[2], this->npc_chars[z].unknown_a2[3]));
|
||||
lines.emplace_back(" name: " + string(this->npc_chars[z].name));
|
||||
for (size_t w = 0; w < 0x78; w += 0x08) {
|
||||
lines.emplace_back(string_printf(" a3[0x%02zX:0x%02zX]=%04hX %04hX %04hX %04hX %04hX %04hX %04hX %04hX",
|
||||
lines.emplace_back(string_printf(
|
||||
" a3[0x%02zX:0x%02zX]=%04hX %04hX %04hX %04hX %04hX %04hX %04hX %04hX",
|
||||
w, w + 0x08,
|
||||
this->npc_chars[z].unknown_a3[w + 0x00].load(), this->npc_chars[z].unknown_a3[w + 0x01].load(),
|
||||
this->npc_chars[z].unknown_a3[w + 0x02].load(), this->npc_chars[z].unknown_a3[w + 0x03].load(),
|
||||
this->npc_chars[z].unknown_a3[w + 0x04].load(), this->npc_chars[z].unknown_a3[w + 0x05].load(),
|
||||
this->npc_chars[z].unknown_a3[w + 0x06].load(), this->npc_chars[z].unknown_a3[w + 0x07].load()));
|
||||
}
|
||||
lines.emplace_back(string_printf(" a3[0x78:0x7E]=%04hX %04hX %04hX %04hX %04hX %04hX",
|
||||
lines.emplace_back(string_printf(
|
||||
" a3[0x78:0x7E]=%04hX %04hX %04hX %04hX %04hX %04hX",
|
||||
this->npc_chars[z].unknown_a3[0x78].load(), this->npc_chars[z].unknown_a3[0x79].load(),
|
||||
this->npc_chars[z].unknown_a3[0x7A].load(), this->npc_chars[z].unknown_a3[0x7B].load(),
|
||||
this->npc_chars[z].unknown_a3[0x7C].load(), this->npc_chars[z].unknown_a3[0x7D].load()));
|
||||
@@ -1129,7 +1116,8 @@ string MapDefinition::str(const DataIndex* data_index) const {
|
||||
if (data_index) {
|
||||
try {
|
||||
entry = data_index->definition_for_card_id(card_id);
|
||||
} catch (const out_of_range&) { }
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
}
|
||||
if (entry) {
|
||||
string name = entry->def.en_name;
|
||||
@@ -1152,7 +1140,7 @@ string MapDefinition::str(const DataIndex* data_index) const {
|
||||
}
|
||||
lines.emplace_back(" a7a=" + format_data_string(this->unknown_a7_a.data(), this->unknown_a7_a.bytes()));
|
||||
lines.emplace_back(string_printf(" a7b=[%08" PRIX32 " %08" PRIX32 " %08" PRIX32 "]",
|
||||
this->unknown_a7_b[0].load(), this->unknown_a7_b[1].load(), this->unknown_a7_b[2].load()));
|
||||
this->unknown_a7_b[0].load(), this->unknown_a7_b[1].load(), this->unknown_a7_b[2].load()));
|
||||
if (this->before_message[0]) {
|
||||
lines.emplace_back(" before_message: " + string(this->before_message));
|
||||
}
|
||||
@@ -1168,7 +1156,8 @@ string MapDefinition::str(const DataIndex* data_index) const {
|
||||
if (data_index) {
|
||||
try {
|
||||
entry = data_index->definition_for_card_id(card_id);
|
||||
} catch (const out_of_range&) { }
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
}
|
||||
if (entry) {
|
||||
string name = entry->def.en_name;
|
||||
@@ -1178,35 +1167,35 @@ string MapDefinition::str(const DataIndex* data_index) const {
|
||||
}
|
||||
}
|
||||
lines.emplace_back(string_printf(" a9=[%08" PRIX32 " %08" PRIX32 " %04hX %04hX]",
|
||||
this->unknown_a9_a.load(), this->unknown_a9_b.load(), this->unknown_a9_c.load(), this->unknown_a9_d.load()));
|
||||
this->unknown_a9_a.load(), this->unknown_a9_b.load(), this->unknown_a9_c.load(), this->unknown_a9_d.load()));
|
||||
lines.emplace_back(string_printf(" a10=%02hhX", this->unknown_a10));
|
||||
lines.emplace_back(string_printf(" cyber_block_type=%02hhX", this->cyber_block_type));
|
||||
lines.emplace_back(string_printf(" a11=%02hhX%02hhX", this->unknown_a11[0], this->unknown_a11[1]));
|
||||
static const array<const char*, 0x18> sc_card_entry_names = {
|
||||
"00 (Guykild; 0005)",
|
||||
"01 (Kylria; 0006)",
|
||||
"02 (Saligun; 0110)",
|
||||
"03 (Relmitos; 0111)",
|
||||
"04 (Kranz; 0002)",
|
||||
"05 (Sil'fer; 0004)",
|
||||
"06 (Ino'lis; 0003)",
|
||||
"07 (Viviana; 0112)",
|
||||
"08 (Teifu; 0113)",
|
||||
"09 (Orland; 0001)",
|
||||
"0A (Stella; 0114)",
|
||||
"0B (Glustar; 0115)",
|
||||
"0C (Hyze; 0117)",
|
||||
"0D (Rufina; 0118)",
|
||||
"0E (Peko; 0119)",
|
||||
"0F (Creinu; 011A)",
|
||||
"10 (Reiz; 011B)",
|
||||
"11 (Lura; 0007)",
|
||||
"12 (Break; 0008)",
|
||||
"13 (Rio; 011C)",
|
||||
"14 (Endu; 0116)",
|
||||
"15 (Memoru; 011D)",
|
||||
"16 (K.C.; 011E)",
|
||||
"17 (Ohgun; 011F)",
|
||||
"00 (Guykild; 0005)",
|
||||
"01 (Kylria; 0006)",
|
||||
"02 (Saligun; 0110)",
|
||||
"03 (Relmitos; 0111)",
|
||||
"04 (Kranz; 0002)",
|
||||
"05 (Sil'fer; 0004)",
|
||||
"06 (Ino'lis; 0003)",
|
||||
"07 (Viviana; 0112)",
|
||||
"08 (Teifu; 0113)",
|
||||
"09 (Orland; 0001)",
|
||||
"0A (Stella; 0114)",
|
||||
"0B (Glustar; 0115)",
|
||||
"0C (Hyze; 0117)",
|
||||
"0D (Rufina; 0118)",
|
||||
"0E (Peko; 0119)",
|
||||
"0F (Creinu; 011A)",
|
||||
"10 (Reiz; 011B)",
|
||||
"11 (Lura; 0007)",
|
||||
"12 (Break; 0008)",
|
||||
"13 (Rio; 011C)",
|
||||
"14 (Endu; 0116)",
|
||||
"15 (Memoru; 011D)",
|
||||
"16 (K.C.; 011E)",
|
||||
"17 (Ohgun; 011F)",
|
||||
};
|
||||
string unavailable_sc_cards = " unavailable_sc_cards=[";
|
||||
for (size_t z = 0; z < 0x18; z++) {
|
||||
@@ -1338,10 +1327,8 @@ bool Rules::check_and_reset_invalid_fields() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DataIndex::DataIndex(const string& directory, uint32_t behavior_flags)
|
||||
: behavior_flags(behavior_flags) {
|
||||
: behavior_flags(behavior_flags) {
|
||||
|
||||
unordered_map<uint32_t, vector<string>> card_tags;
|
||||
unordered_map<uint32_t, string> card_text;
|
||||
@@ -1487,10 +1474,12 @@ DataIndex::DataIndex(const string& directory, uint32_t behavior_flags)
|
||||
if (this->behavior_flags & BehaviorFlag::LOAD_CARD_TEXT) {
|
||||
try {
|
||||
entry->text = move(card_text.at(defs[x].card_id));
|
||||
} catch (const out_of_range&) { }
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
try {
|
||||
entry->debug_tags = move(card_tags.at(defs[x].card_id));
|
||||
} catch (const out_of_range&) { }
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1533,13 +1522,13 @@ DataIndex::DataIndex(const string& directory, uint32_t behavior_flags)
|
||||
this->maps_by_name.emplace(entry->map.name, entry);
|
||||
string name = entry->map.name;
|
||||
static_game_data_log.info("Indexed Episode 3 %s %s (%08" PRIX32 "; %s)",
|
||||
is_quest ? "online quest" : "free battle map",
|
||||
filename.c_str(), entry->map.map_number.load(), name.c_str());
|
||||
is_quest ? "online quest" : "free battle map",
|
||||
filename.c_str(), entry->map.map_number.load(), name.c_str());
|
||||
}
|
||||
|
||||
} catch (const exception& e) {
|
||||
static_game_data_log.warning("Failed to index Episode 3 map %s: %s",
|
||||
filename.c_str(), e.what());
|
||||
filename.c_str(), e.what());
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1567,10 +1556,12 @@ DataIndex::DataIndex(const string& directory, uint32_t behavior_flags)
|
||||
}
|
||||
|
||||
DataIndex::MapEntry::MapEntry(const MapDefinition& map, bool is_quest)
|
||||
: map(map), is_quest(is_quest) { }
|
||||
: map(map),
|
||||
is_quest(is_quest) {}
|
||||
|
||||
DataIndex::MapEntry::MapEntry(const string& compressed, bool is_quest)
|
||||
: is_quest(is_quest), compressed_data(compressed) {
|
||||
: is_quest(is_quest),
|
||||
compressed_data(compressed) {
|
||||
string decompressed = prs_decompress(this->compressed_data);
|
||||
if (decompressed.size() != sizeof(MapDefinition)) {
|
||||
throw runtime_error(string_printf(
|
||||
@@ -1673,7 +1664,7 @@ const string& DataIndex::get_compressed_map_list() const {
|
||||
}
|
||||
size_t decompressed_size = sizeof(header) + entries_w.size() + strings_w.size();
|
||||
static_game_data_log.info("Generated Episode 3 compressed map list (0x%zX -> 0x%zX bytes)",
|
||||
decompressed_size, this->compressed_map_list.size());
|
||||
decompressed_size, this->compressed_map_list.size());
|
||||
}
|
||||
return this->compressed_map_list;
|
||||
}
|
||||
@@ -1711,8 +1702,6 @@ shared_ptr<const COMDeckDefinition> DataIndex::random_com_deck() const {
|
||||
return this->com_decks[random_object<size_t>() % this->com_decks.size()];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PlayerConfig::decrypt() {
|
||||
if (!this->is_encrypted) {
|
||||
return;
|
||||
@@ -1740,6 +1729,4 @@ void PlayerConfig::encrypt(uint8_t basis) {
|
||||
this->basis = basis;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
+254
-270
@@ -2,42 +2,36 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <phosg/Encoding.hh>
|
||||
#include <phosg/JSON.hh>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "../Text.hh"
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
// The comment in Server.hh does not apply to this file (and DataIndex.cc).
|
||||
// Except for the Location structure, these structures and functions are not
|
||||
// based on Sega's original implementation.
|
||||
|
||||
class DataIndex;
|
||||
|
||||
|
||||
|
||||
enum BehaviorFlag {
|
||||
SKIP_DECK_VERIFY = 0x00000001,
|
||||
IGNORE_CARD_COUNTS = 0x00000002,
|
||||
SKIP_D1_D2_REPLACE = 0x00000004,
|
||||
DISABLE_TIME_LIMITS = 0x00000008,
|
||||
SKIP_DECK_VERIFY = 0x00000001,
|
||||
IGNORE_CARD_COUNTS = 0x00000002,
|
||||
SKIP_D1_D2_REPLACE = 0x00000004,
|
||||
DISABLE_TIME_LIMITS = 0x00000008,
|
||||
ENABLE_STATUS_MESSAGES = 0x00000010,
|
||||
LOAD_CARD_TEXT = 0x00000020,
|
||||
ENABLE_RECORDING = 0x00000040,
|
||||
DISABLE_MASKING = 0x00000080,
|
||||
DISABLE_INTERFERENCE = 0x00000100,
|
||||
LOAD_CARD_TEXT = 0x00000020,
|
||||
ENABLE_RECORDING = 0x00000040,
|
||||
DISABLE_MASKING = 0x00000080,
|
||||
DISABLE_INTERFERENCE = 0x00000100,
|
||||
};
|
||||
|
||||
|
||||
|
||||
enum class StatSwapType : uint8_t {
|
||||
NONE = 0,
|
||||
A_T_SWAP = 1,
|
||||
@@ -99,54 +93,54 @@ enum class CriterionCode : uint8_t {
|
||||
};
|
||||
|
||||
enum class CardRarity : uint8_t {
|
||||
N1 = 0x01,
|
||||
R1 = 0x02,
|
||||
S = 0x03,
|
||||
E = 0x04,
|
||||
N2 = 0x05,
|
||||
N3 = 0x06,
|
||||
N4 = 0x07,
|
||||
R2 = 0x08,
|
||||
R3 = 0x09,
|
||||
R4 = 0x0A,
|
||||
SS = 0x0B,
|
||||
D1 = 0x0C,
|
||||
D2 = 0x0D,
|
||||
N1 = 0x01,
|
||||
R1 = 0x02,
|
||||
S = 0x03,
|
||||
E = 0x04,
|
||||
N2 = 0x05,
|
||||
N3 = 0x06,
|
||||
N4 = 0x07,
|
||||
R2 = 0x08,
|
||||
R3 = 0x09,
|
||||
R4 = 0x0A,
|
||||
SS = 0x0B,
|
||||
D1 = 0x0C,
|
||||
D2 = 0x0D,
|
||||
INVIS = 0x0E,
|
||||
};
|
||||
|
||||
enum class CardType : uint8_t {
|
||||
HUNTERS_SC = 0x00,
|
||||
ARKZ_SC = 0x01,
|
||||
ITEM = 0x02,
|
||||
CREATURE = 0x03,
|
||||
ACTION = 0x04,
|
||||
ASSIST = 0x05,
|
||||
ARKZ_SC = 0x01,
|
||||
ITEM = 0x02,
|
||||
CREATURE = 0x03,
|
||||
ACTION = 0x04,
|
||||
ASSIST = 0x05,
|
||||
INVALID_FF = 0xFF,
|
||||
END_CARD_LIST = 0xFF,
|
||||
};
|
||||
|
||||
enum class CardClass : uint16_t {
|
||||
HU_SC = 0x0000,
|
||||
RA_SC = 0x0001,
|
||||
FO_SC = 0x0002,
|
||||
NATIVE_CREATURE = 0x000A,
|
||||
A_BEAST_CREATURE = 0x000B,
|
||||
MACHINE_CREATURE = 0x000C,
|
||||
DARK_CREATURE = 0x000D,
|
||||
GUARD_ITEM = 0x0015,
|
||||
MAG_ITEM = 0x0017,
|
||||
SWORD_ITEM = 0x0018,
|
||||
GUN_ITEM = 0x0019,
|
||||
CANE_ITEM = 0x001A,
|
||||
ATTACK_ACTION = 0x001E,
|
||||
DEFENSE_ACTION = 0x001F,
|
||||
TECH = 0x0020,
|
||||
PHOTON_BLAST = 0x0021,
|
||||
HU_SC = 0x0000,
|
||||
RA_SC = 0x0001,
|
||||
FO_SC = 0x0002,
|
||||
NATIVE_CREATURE = 0x000A,
|
||||
A_BEAST_CREATURE = 0x000B,
|
||||
MACHINE_CREATURE = 0x000C,
|
||||
DARK_CREATURE = 0x000D,
|
||||
GUARD_ITEM = 0x0015,
|
||||
MAG_ITEM = 0x0017,
|
||||
SWORD_ITEM = 0x0018,
|
||||
GUN_ITEM = 0x0019,
|
||||
CANE_ITEM = 0x001A,
|
||||
ATTACK_ACTION = 0x001E,
|
||||
DEFENSE_ACTION = 0x001F,
|
||||
TECH = 0x0020,
|
||||
PHOTON_BLAST = 0x0021,
|
||||
CONNECT_ONLY_ATTACK_ACTION = 0x0022,
|
||||
BOSS_ATTACK_ACTION = 0x0023,
|
||||
BOSS_TECH = 0x0024,
|
||||
ASSIST = 0x0028,
|
||||
BOSS_ATTACK_ACTION = 0x0023,
|
||||
BOSS_TECH = 0x0024,
|
||||
ASSIST = 0x0028,
|
||||
};
|
||||
|
||||
bool card_class_is_tech_like(CardClass cc);
|
||||
@@ -165,216 +159,216 @@ enum class TargetMode : uint8_t {
|
||||
};
|
||||
|
||||
enum class ConditionType : uint8_t {
|
||||
NONE = 0x00,
|
||||
AP_BOOST = 0x01, // Temporarily increase AP by N
|
||||
RAMPAGE = 0x02,
|
||||
MULTI_STRIKE = 0x03, // Duplicate attack N times
|
||||
DAMAGE_MOD_1 = 0x04, // Set attack damage / AP to N after action cards applied (step 1)
|
||||
IMMOBILE = 0x05, // Give Immobile condition
|
||||
HOLD = 0x06, // Give Hold condition
|
||||
UNKNOWN_07 = 0x07,
|
||||
TP_BOOST = 0x08, // Add N TP temporarily during attack
|
||||
GIVE_DAMAGE = 0x09, // Cause direct N HP loss
|
||||
GUOM = 0x0A, // Give Guom condition
|
||||
PARALYZE = 0x0B, // Give Paralysis condition
|
||||
UNKNOWN_0C = 0x0C, // Swap AP and TP temporarily (presumably)
|
||||
A_H_SWAP = 0x0D, // Swap AP and HP temporarily
|
||||
PIERCE = 0x0E, // Attack SC directly even if they have items equipped
|
||||
UNKNOWN_0F = 0x0F,
|
||||
HEAL = 0x10, // Increase HP by N
|
||||
RETURN_TO_HAND = 0x11, // Return card to hand
|
||||
UNKNOWN_12 = 0x12,
|
||||
UNKNOWN_13 = 0x13,
|
||||
ACID = 0x14, // Give Acid condition
|
||||
UNKNOWN_15 = 0x15,
|
||||
MIGHTY_KNUCKLE = 0x16, // Temporarily increase AP by N, and set ATK dice to zero
|
||||
UNIT_BLOW = 0x17, // Temporarily increase AP by N * number of this card set within phase
|
||||
CURSE = 0x18, // Give Curse condition
|
||||
COMBO_AP = 0x19, // Temporarily increase AP by number of this card set within phase
|
||||
NONE = 0x00,
|
||||
AP_BOOST = 0x01, // Temporarily increase AP by N
|
||||
RAMPAGE = 0x02,
|
||||
MULTI_STRIKE = 0x03, // Duplicate attack N times
|
||||
DAMAGE_MOD_1 = 0x04, // Set attack damage / AP to N after action cards applied (step 1)
|
||||
IMMOBILE = 0x05, // Give Immobile condition
|
||||
HOLD = 0x06, // Give Hold condition
|
||||
UNKNOWN_07 = 0x07,
|
||||
TP_BOOST = 0x08, // Add N TP temporarily during attack
|
||||
GIVE_DAMAGE = 0x09, // Cause direct N HP loss
|
||||
GUOM = 0x0A, // Give Guom condition
|
||||
PARALYZE = 0x0B, // Give Paralysis condition
|
||||
UNKNOWN_0C = 0x0C, // Swap AP and TP temporarily (presumably)
|
||||
A_H_SWAP = 0x0D, // Swap AP and HP temporarily
|
||||
PIERCE = 0x0E, // Attack SC directly even if they have items equipped
|
||||
UNKNOWN_0F = 0x0F,
|
||||
HEAL = 0x10, // Increase HP by N
|
||||
RETURN_TO_HAND = 0x11, // Return card to hand
|
||||
UNKNOWN_12 = 0x12,
|
||||
UNKNOWN_13 = 0x13,
|
||||
ACID = 0x14, // Give Acid condition
|
||||
UNKNOWN_15 = 0x15,
|
||||
MIGHTY_KNUCKLE = 0x16, // Temporarily increase AP by N, and set ATK dice to zero
|
||||
UNIT_BLOW = 0x17, // Temporarily increase AP by N * number of this card set within phase
|
||||
CURSE = 0x18, // Give Curse condition
|
||||
COMBO_AP = 0x19, // Temporarily increase AP by number of this card set within phase
|
||||
PIERCE_RAMPAGE_BLOCK = 0x1A, // Block attack if Pierce/Rampage
|
||||
ABILITY_TRAP = 0x1B, // Temporarily disable opponent abilities
|
||||
FREEZE = 0x1C, // Give Freeze condition
|
||||
ANTI_ABNORMALITY_1 = 0x1D, // Cure all abnormal conditions
|
||||
UNKNOWN_1E = 0x1E,
|
||||
EXPLOSION = 0x1F, // Damage all SCs and FCs by number of this same card set * 2
|
||||
UNKNOWN_20 = 0x20,
|
||||
UNKNOWN_21 = 0x21,
|
||||
UNKNOWN_22 = 0x22,
|
||||
RETURN_TO_DECK = 0x23, // Cancel discard and move to bottom of deck instead
|
||||
AERIAL = 0x24, // Give Aerial status
|
||||
AP_LOSS = 0x25, // Make attacker temporarily lose N AP during defense
|
||||
BONUS_FROM_LEADER = 0x26, // Gain AP equal to the number of cards of type N on the field
|
||||
FREE_MANEUVER = 0x27, // Enable movement over occupied tiles
|
||||
HASTE = 0x28, // Multiply all move action costs by expr (which may be zero)
|
||||
CLONE = 0x29, // Make setting this card free if at least one card of type N is already on the field
|
||||
DEF_DISABLE_BY_COST = 0x2A, // Disable use of any defense cards costing between (N / 10) and (N % 10) points, inclusive
|
||||
FILIAL = 0x2B, // Increase controlling SC's HP by N when this card is destroyed
|
||||
SNATCH = 0x2C, // Steal N EXP during attack
|
||||
HAND_DISRUPTER = 0x2D, // Discard N cards from hand immediately
|
||||
DROP = 0x2E, // Give Drop condition
|
||||
ACTION_DISRUPTER = 0x2F, // Destroy all action cards used by attacker
|
||||
SET_HP = 0x30, // Set HP to N
|
||||
NATIVE_SHIELD = 0x31, // Block attacks from Native creatures
|
||||
A_BEAST_SHIELD = 0x32, // Block attacks from A.Beast creatures
|
||||
MACHINE_SHIELD = 0x33, // Block attacks from Machine creatures
|
||||
DARK_SHIELD = 0x34, // Block attacks from Dark creatures
|
||||
SWORD_SHIELD = 0x35, // Block attacks from Sword items
|
||||
GUN_SHIELD = 0x36, // Block attacks from Gun items
|
||||
CANE_SHIELD = 0x37, // Block attacks from Cane items
|
||||
UNKNOWN_38 = 0x38,
|
||||
UNKNOWN_39 = 0x39,
|
||||
DEFENDER = 0x3A, // Make attacks go to setter of this card instead of original target
|
||||
SURVIVAL_DECOYS = 0x3B, // Redirect damage for multi-sided attack
|
||||
GIVE_OR_TAKE_EXP = 0x3C, // Give N EXP, or take if N is negative
|
||||
UNKNOWN_3D = 0x3D,
|
||||
DEATH_COMPANION = 0x3E, // If this card has 1 or 2 HP, set its HP to N
|
||||
EXP_DECOY = 0x3F, // If defender has EXP, lose EXP instead of getting damage when attacked
|
||||
SET_MV = 0x40, // Set MV to N
|
||||
GROUP = 0x41, // Temporarily increase AP by N * number of this card on field, excluding itself
|
||||
BERSERK = 0x42, // User of this card receives the same damage as target, and isn't helped by target's defense cards
|
||||
GUARD_CREATURE = 0x43, // Attacks on controlling SC damage this card instead
|
||||
TECH = 0x44, // Technique cards cost 1 fewer ATK point
|
||||
BIG_SWING = 0x45, // Increase all attacking ATK costs by 1
|
||||
UNKNOWN_46 = 0x46,
|
||||
SHIELD_WEAPON = 0x47, // Limit attacker's choice of target to guard items
|
||||
ATK_DICE_BOOST = 0x48, // Increase ATK dice roll by 1
|
||||
UNKNOWN_49 = 0x49,
|
||||
MAJOR_PIERCE = 0x4A, // If SC has over half of max HP, attacks target SC instead of equipped items
|
||||
HEAVY_PIERCE = 0x4B, // If SC has 3 or more items equipped, attacks target SC instead of equipped items
|
||||
MAJOR_RAMPAGE = 0x4C, // If SC has over half of max HP, attacks target SC and all equipped items
|
||||
HEAVY_RAMPAGE = 0x4D, // If SC has 3 or more items equipped, attacks target SC and all equipped items
|
||||
AP_GROWTH = 0x4E, // Permanently increase AP by N
|
||||
TP_GROWTH = 0x4F, // Permanently increase TP by N
|
||||
REBORN = 0x50, // If any card of type N is on the field, this card goes to the hand when destroyed instead of being discarded
|
||||
COPY = 0x51, // Temporarily set AP/TP to N percent (or 100% if N is 0) of opponent's values
|
||||
UNKNOWN_52 = 0x52,
|
||||
MISC_GUARDS = 0x53, // Add N to card's defense value
|
||||
AP_OVERRIDE = 0x54, // Set AP to N temporarily
|
||||
TP_OVERRIDE = 0x55, // Set TP to N temporarily
|
||||
RETURN = 0x56, // Return card to hand on destruction instead of discarding
|
||||
A_T_SWAP_PERM = 0x57, // Permanently swap AP and TP
|
||||
A_H_SWAP_PERM = 0x58, // Permanently swap AP and HP
|
||||
SLAYERS_ASSASSINS = 0x59, // Temporarily increase AP during attack
|
||||
ANTI_ABNORMALITY_2 = 0x5A, // Remove all conditions
|
||||
FIXED_RANGE = 0x5B, // Use SC's range instead of weapon or attack card ranges
|
||||
ELUDE = 0x5C, // SC does not lose HP when equipped items are destroyed
|
||||
PARRY = 0x5D, // Forward attack to a random FC within one tile of original target, excluding attacker and original target
|
||||
BLOCK_ATTACK = 0x5E, // Completely block attack
|
||||
UNKNOWN_5F = 0x5F,
|
||||
UNKNOWN_60 = 0x60,
|
||||
COMBO_TP = 0x61, // Gain TP equal to the number of cards of type N on the field
|
||||
MISC_AP_BONUSES = 0x62, // Temporarily increase AP by N
|
||||
MISC_TP_BONUSES = 0x63, // Temporarily increase TP by N
|
||||
UNKNOWN_64 = 0x64,
|
||||
ABILITY_TRAP = 0x1B, // Temporarily disable opponent abilities
|
||||
FREEZE = 0x1C, // Give Freeze condition
|
||||
ANTI_ABNORMALITY_1 = 0x1D, // Cure all abnormal conditions
|
||||
UNKNOWN_1E = 0x1E,
|
||||
EXPLOSION = 0x1F, // Damage all SCs and FCs by number of this same card set * 2
|
||||
UNKNOWN_20 = 0x20,
|
||||
UNKNOWN_21 = 0x21,
|
||||
UNKNOWN_22 = 0x22,
|
||||
RETURN_TO_DECK = 0x23, // Cancel discard and move to bottom of deck instead
|
||||
AERIAL = 0x24, // Give Aerial status
|
||||
AP_LOSS = 0x25, // Make attacker temporarily lose N AP during defense
|
||||
BONUS_FROM_LEADER = 0x26, // Gain AP equal to the number of cards of type N on the field
|
||||
FREE_MANEUVER = 0x27, // Enable movement over occupied tiles
|
||||
HASTE = 0x28, // Multiply all move action costs by expr (which may be zero)
|
||||
CLONE = 0x29, // Make setting this card free if at least one card of type N is already on the field
|
||||
DEF_DISABLE_BY_COST = 0x2A, // Disable use of any defense cards costing between (N / 10) and (N % 10) points, inclusive
|
||||
FILIAL = 0x2B, // Increase controlling SC's HP by N when this card is destroyed
|
||||
SNATCH = 0x2C, // Steal N EXP during attack
|
||||
HAND_DISRUPTER = 0x2D, // Discard N cards from hand immediately
|
||||
DROP = 0x2E, // Give Drop condition
|
||||
ACTION_DISRUPTER = 0x2F, // Destroy all action cards used by attacker
|
||||
SET_HP = 0x30, // Set HP to N
|
||||
NATIVE_SHIELD = 0x31, // Block attacks from Native creatures
|
||||
A_BEAST_SHIELD = 0x32, // Block attacks from A.Beast creatures
|
||||
MACHINE_SHIELD = 0x33, // Block attacks from Machine creatures
|
||||
DARK_SHIELD = 0x34, // Block attacks from Dark creatures
|
||||
SWORD_SHIELD = 0x35, // Block attacks from Sword items
|
||||
GUN_SHIELD = 0x36, // Block attacks from Gun items
|
||||
CANE_SHIELD = 0x37, // Block attacks from Cane items
|
||||
UNKNOWN_38 = 0x38,
|
||||
UNKNOWN_39 = 0x39,
|
||||
DEFENDER = 0x3A, // Make attacks go to setter of this card instead of original target
|
||||
SURVIVAL_DECOYS = 0x3B, // Redirect damage for multi-sided attack
|
||||
GIVE_OR_TAKE_EXP = 0x3C, // Give N EXP, or take if N is negative
|
||||
UNKNOWN_3D = 0x3D,
|
||||
DEATH_COMPANION = 0x3E, // If this card has 1 or 2 HP, set its HP to N
|
||||
EXP_DECOY = 0x3F, // If defender has EXP, lose EXP instead of getting damage when attacked
|
||||
SET_MV = 0x40, // Set MV to N
|
||||
GROUP = 0x41, // Temporarily increase AP by N * number of this card on field, excluding itself
|
||||
BERSERK = 0x42, // User of this card receives the same damage as target, and isn't helped by target's defense cards
|
||||
GUARD_CREATURE = 0x43, // Attacks on controlling SC damage this card instead
|
||||
TECH = 0x44, // Technique cards cost 1 fewer ATK point
|
||||
BIG_SWING = 0x45, // Increase all attacking ATK costs by 1
|
||||
UNKNOWN_46 = 0x46,
|
||||
SHIELD_WEAPON = 0x47, // Limit attacker's choice of target to guard items
|
||||
ATK_DICE_BOOST = 0x48, // Increase ATK dice roll by 1
|
||||
UNKNOWN_49 = 0x49,
|
||||
MAJOR_PIERCE = 0x4A, // If SC has over half of max HP, attacks target SC instead of equipped items
|
||||
HEAVY_PIERCE = 0x4B, // If SC has 3 or more items equipped, attacks target SC instead of equipped items
|
||||
MAJOR_RAMPAGE = 0x4C, // If SC has over half of max HP, attacks target SC and all equipped items
|
||||
HEAVY_RAMPAGE = 0x4D, // If SC has 3 or more items equipped, attacks target SC and all equipped items
|
||||
AP_GROWTH = 0x4E, // Permanently increase AP by N
|
||||
TP_GROWTH = 0x4F, // Permanently increase TP by N
|
||||
REBORN = 0x50, // If any card of type N is on the field, this card goes to the hand when destroyed instead of being discarded
|
||||
COPY = 0x51, // Temporarily set AP/TP to N percent (or 100% if N is 0) of opponent's values
|
||||
UNKNOWN_52 = 0x52,
|
||||
MISC_GUARDS = 0x53, // Add N to card's defense value
|
||||
AP_OVERRIDE = 0x54, // Set AP to N temporarily
|
||||
TP_OVERRIDE = 0x55, // Set TP to N temporarily
|
||||
RETURN = 0x56, // Return card to hand on destruction instead of discarding
|
||||
A_T_SWAP_PERM = 0x57, // Permanently swap AP and TP
|
||||
A_H_SWAP_PERM = 0x58, // Permanently swap AP and HP
|
||||
SLAYERS_ASSASSINS = 0x59, // Temporarily increase AP during attack
|
||||
ANTI_ABNORMALITY_2 = 0x5A, // Remove all conditions
|
||||
FIXED_RANGE = 0x5B, // Use SC's range instead of weapon or attack card ranges
|
||||
ELUDE = 0x5C, // SC does not lose HP when equipped items are destroyed
|
||||
PARRY = 0x5D, // Forward attack to a random FC within one tile of original target, excluding attacker and original target
|
||||
BLOCK_ATTACK = 0x5E, // Completely block attack
|
||||
UNKNOWN_5F = 0x5F,
|
||||
UNKNOWN_60 = 0x60,
|
||||
COMBO_TP = 0x61, // Gain TP equal to the number of cards of type N on the field
|
||||
MISC_AP_BONUSES = 0x62, // Temporarily increase AP by N
|
||||
MISC_TP_BONUSES = 0x63, // Temporarily increase TP by N
|
||||
UNKNOWN_64 = 0x64,
|
||||
MISC_DEFENSE_BONUSES = 0x65, // Decrease damage by N
|
||||
MOSTLY_HALFGUARDS = 0x66, // Reduce damage from incoming attack by N
|
||||
PERIODIC_FIELD = 0x67, // Swap immunity to tech or physical attacks
|
||||
FC_LIMIT_BY_COUNT = 0x68, // Change FC limit from 8 ATK points total to 4 FCs total
|
||||
UNKNOWN_69 = 0x69,
|
||||
MV_BONUS = 0x6A, // Increase MV by N
|
||||
FORWARD_DAMAGE = 0x6B,
|
||||
WEAK_SPOT_INFLUENCE = 0x6C, // Temporarily decrease AP by N
|
||||
DAMAGE_MODIFIER_2 = 0x6D, // Set attack damage / AP after action cards applied (step 2)
|
||||
WEAK_HIT_BLOCK = 0x6E, // Block all attacks of N damage or less
|
||||
AP_SILENCE = 0x6F, // Temporarily decrease AP of opponent by N
|
||||
TP_SILENCE = 0x70, // Temporarily decrease TP of opponent by N
|
||||
A_T_SWAP = 0x71, // Temporarily swap AP and TP
|
||||
HALFGUARD = 0x72, // Halve damage from attacks that would inflict N or more damage
|
||||
UNKNOWN_73 = 0x73,
|
||||
RAMPAGE_AP_LOSS = 0x74, // Temporarily reduce AP by N
|
||||
UNKNOWN_75 = 0x75,
|
||||
REFLECT = 0x76, // Generate reverse attack
|
||||
UNKNOWN_77 = 0x77,
|
||||
ANY = 0x78, // Not a real condition; used as a wildcard in search functions
|
||||
UNKNOWN_79 = 0x79,
|
||||
UNKNOWN_7A = 0x7A,
|
||||
UNKNOWN_7B = 0x7B,
|
||||
UNKNOWN_7C = 0x7C,
|
||||
UNKNOWN_7D = 0x7D,
|
||||
INVALID_FF = 0xFF,
|
||||
ANY_FF = 0xFF, // Used as a wildcard in some search functions
|
||||
MOSTLY_HALFGUARDS = 0x66, // Reduce damage from incoming attack by N
|
||||
PERIODIC_FIELD = 0x67, // Swap immunity to tech or physical attacks
|
||||
FC_LIMIT_BY_COUNT = 0x68, // Change FC limit from 8 ATK points total to 4 FCs total
|
||||
UNKNOWN_69 = 0x69,
|
||||
MV_BONUS = 0x6A, // Increase MV by N
|
||||
FORWARD_DAMAGE = 0x6B,
|
||||
WEAK_SPOT_INFLUENCE = 0x6C, // Temporarily decrease AP by N
|
||||
DAMAGE_MODIFIER_2 = 0x6D, // Set attack damage / AP after action cards applied (step 2)
|
||||
WEAK_HIT_BLOCK = 0x6E, // Block all attacks of N damage or less
|
||||
AP_SILENCE = 0x6F, // Temporarily decrease AP of opponent by N
|
||||
TP_SILENCE = 0x70, // Temporarily decrease TP of opponent by N
|
||||
A_T_SWAP = 0x71, // Temporarily swap AP and TP
|
||||
HALFGUARD = 0x72, // Halve damage from attacks that would inflict N or more damage
|
||||
UNKNOWN_73 = 0x73,
|
||||
RAMPAGE_AP_LOSS = 0x74, // Temporarily reduce AP by N
|
||||
UNKNOWN_75 = 0x75,
|
||||
REFLECT = 0x76, // Generate reverse attack
|
||||
UNKNOWN_77 = 0x77,
|
||||
ANY = 0x78, // Not a real condition; used as a wildcard in search functions
|
||||
UNKNOWN_79 = 0x79,
|
||||
UNKNOWN_7A = 0x7A,
|
||||
UNKNOWN_7B = 0x7B,
|
||||
UNKNOWN_7C = 0x7C,
|
||||
UNKNOWN_7D = 0x7D,
|
||||
INVALID_FF = 0xFF,
|
||||
ANY_FF = 0xFF, // Used as a wildcard in some search functions
|
||||
};
|
||||
|
||||
const char* name_for_condition_type(ConditionType cond_type);
|
||||
|
||||
enum class AssistEffect : uint16_t {
|
||||
NONE = 0x0000,
|
||||
DICE_HALF = 0x0001,
|
||||
DICE_PLUS_1 = 0x0002,
|
||||
DICE_FEVER = 0x0003,
|
||||
CARD_RETURN = 0x0004,
|
||||
LAND_PRICE = 0x0005,
|
||||
POWERLESS_RAIN = 0x0006,
|
||||
BRAVE_WIND = 0x0007,
|
||||
SILENT_COLOSSEUM = 0x0008,
|
||||
RESISTANCE = 0x0009,
|
||||
INDEPENDENT = 0x000A,
|
||||
ASSISTLESS = 0x000B,
|
||||
ATK_DICE_2 = 0x000C,
|
||||
DEFLATION = 0x000D,
|
||||
INFLATION = 0x000E,
|
||||
EXCHANGE = 0x000F,
|
||||
INFLUENCE = 0x0010,
|
||||
SKIP_SET = 0x0011,
|
||||
SKIP_MOVE = 0x0012,
|
||||
SKIP_ACT = 0x0013,
|
||||
SKIP_DRAW = 0x0014,
|
||||
FLY = 0x0015,
|
||||
NECROMANCER = 0x0016,
|
||||
PERMISSION = 0x0017,
|
||||
SHUFFLE_ALL = 0x0018,
|
||||
LEGACY = 0x0019,
|
||||
ASSIST_REVERSE = 0x001A,
|
||||
STAMINA = 0x001B,
|
||||
AP_ABSORPTION = 0x001C,
|
||||
HEAVY_FOG = 0x001D,
|
||||
TRASH_1 = 0x001E,
|
||||
EMPTY_HAND = 0x001F,
|
||||
HITMAN = 0x0020,
|
||||
ASSIST_TRASH = 0x0021,
|
||||
SHUFFLE_GROUP = 0x0022,
|
||||
ASSIST_VANISH = 0x0023,
|
||||
CHARITY = 0x0024,
|
||||
INHERITANCE = 0x0025,
|
||||
FIX = 0x0026,
|
||||
MUSCULAR = 0x0027,
|
||||
CHANGE_BODY = 0x0028,
|
||||
GOD_WHIM = 0x0029,
|
||||
GOLD_RUSH = 0x002A,
|
||||
ASSIST_RETURN = 0x002B,
|
||||
REQUIEM = 0x002C,
|
||||
RANSOM = 0x002D,
|
||||
SIMPLE = 0x002E,
|
||||
SLOW_TIME = 0x002F,
|
||||
QUICK_TIME = 0x0030,
|
||||
TERRITORY = 0x0031,
|
||||
OLD_TYPE = 0x0032,
|
||||
FLATLAND = 0x0033,
|
||||
IMMORTALITY = 0x0034,
|
||||
SNAIL_PACE = 0x0035,
|
||||
TECH_FIELD = 0x0036,
|
||||
FOREST_RAIN = 0x0037,
|
||||
CAVE_WIND = 0x0038,
|
||||
MINE_BRIGHTNESS = 0x0039,
|
||||
RUIN_DARKNESS = 0x003A,
|
||||
SABER_DANCE = 0x003B,
|
||||
BULLET_STORM = 0x003C,
|
||||
CANE_PALACE = 0x003D,
|
||||
GIANT_GARDEN = 0x003E,
|
||||
NONE = 0x0000,
|
||||
DICE_HALF = 0x0001,
|
||||
DICE_PLUS_1 = 0x0002,
|
||||
DICE_FEVER = 0x0003,
|
||||
CARD_RETURN = 0x0004,
|
||||
LAND_PRICE = 0x0005,
|
||||
POWERLESS_RAIN = 0x0006,
|
||||
BRAVE_WIND = 0x0007,
|
||||
SILENT_COLOSSEUM = 0x0008,
|
||||
RESISTANCE = 0x0009,
|
||||
INDEPENDENT = 0x000A,
|
||||
ASSISTLESS = 0x000B,
|
||||
ATK_DICE_2 = 0x000C,
|
||||
DEFLATION = 0x000D,
|
||||
INFLATION = 0x000E,
|
||||
EXCHANGE = 0x000F,
|
||||
INFLUENCE = 0x0010,
|
||||
SKIP_SET = 0x0011,
|
||||
SKIP_MOVE = 0x0012,
|
||||
SKIP_ACT = 0x0013,
|
||||
SKIP_DRAW = 0x0014,
|
||||
FLY = 0x0015,
|
||||
NECROMANCER = 0x0016,
|
||||
PERMISSION = 0x0017,
|
||||
SHUFFLE_ALL = 0x0018,
|
||||
LEGACY = 0x0019,
|
||||
ASSIST_REVERSE = 0x001A,
|
||||
STAMINA = 0x001B,
|
||||
AP_ABSORPTION = 0x001C,
|
||||
HEAVY_FOG = 0x001D,
|
||||
TRASH_1 = 0x001E,
|
||||
EMPTY_HAND = 0x001F,
|
||||
HITMAN = 0x0020,
|
||||
ASSIST_TRASH = 0x0021,
|
||||
SHUFFLE_GROUP = 0x0022,
|
||||
ASSIST_VANISH = 0x0023,
|
||||
CHARITY = 0x0024,
|
||||
INHERITANCE = 0x0025,
|
||||
FIX = 0x0026,
|
||||
MUSCULAR = 0x0027,
|
||||
CHANGE_BODY = 0x0028,
|
||||
GOD_WHIM = 0x0029,
|
||||
GOLD_RUSH = 0x002A,
|
||||
ASSIST_RETURN = 0x002B,
|
||||
REQUIEM = 0x002C,
|
||||
RANSOM = 0x002D,
|
||||
SIMPLE = 0x002E,
|
||||
SLOW_TIME = 0x002F,
|
||||
QUICK_TIME = 0x0030,
|
||||
TERRITORY = 0x0031,
|
||||
OLD_TYPE = 0x0032,
|
||||
FLATLAND = 0x0033,
|
||||
IMMORTALITY = 0x0034,
|
||||
SNAIL_PACE = 0x0035,
|
||||
TECH_FIELD = 0x0036,
|
||||
FOREST_RAIN = 0x0037,
|
||||
CAVE_WIND = 0x0038,
|
||||
MINE_BRIGHTNESS = 0x0039,
|
||||
RUIN_DARKNESS = 0x003A,
|
||||
SABER_DANCE = 0x003B,
|
||||
BULLET_STORM = 0x003C,
|
||||
CANE_PALACE = 0x003D,
|
||||
GIANT_GARDEN = 0x003E,
|
||||
MARCH_OF_THE_MEEK = 0x003F,
|
||||
SUPPORT = 0x0040,
|
||||
RICH = 0x0041,
|
||||
REVERSE_CARD = 0x0042,
|
||||
VENGEANCE = 0x0043,
|
||||
SQUEEZE = 0x0044,
|
||||
HOMESICK = 0x0045,
|
||||
BOMB = 0x0046,
|
||||
SKIP_TURN = 0x0047,
|
||||
BATTLE_ROYALE = 0x0048,
|
||||
DICE_FEVER_PLUS = 0x0049,
|
||||
RICH_PLUS = 0x004A,
|
||||
CHARITY_PLUS = 0x004B,
|
||||
ANY = 0x004C, // Unused on cards; used in some search functions
|
||||
SUPPORT = 0x0040,
|
||||
RICH = 0x0041,
|
||||
REVERSE_CARD = 0x0042,
|
||||
VENGEANCE = 0x0043,
|
||||
SQUEEZE = 0x0044,
|
||||
HOMESICK = 0x0045,
|
||||
BOMB = 0x0046,
|
||||
SKIP_TURN = 0x0047,
|
||||
BATTLE_ROYALE = 0x0048,
|
||||
DICE_FEVER_PLUS = 0x0049,
|
||||
RICH_PLUS = 0x004A,
|
||||
CHARITY_PLUS = 0x004B,
|
||||
ANY = 0x004C, // Unused on cards; used in some search functions
|
||||
};
|
||||
|
||||
enum class BattlePhase : uint8_t {
|
||||
@@ -413,8 +407,6 @@ enum class RegistrationPhase : uint8_t {
|
||||
INVALID_FF = 0xFF,
|
||||
};
|
||||
|
||||
|
||||
|
||||
enum class Direction : uint8_t {
|
||||
RIGHT = 0,
|
||||
UP = 1,
|
||||
@@ -711,8 +703,6 @@ struct StateFlags {
|
||||
void clear_FF();
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
|
||||
struct MapList {
|
||||
be_uint32_t num_maps;
|
||||
be_uint32_t unknown_a1; // Always 0?
|
||||
@@ -875,10 +865,10 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
|
||||
|
||||
/* 59B0 */ parray<be_uint16_t, 0x10> reward_card_ids;
|
||||
|
||||
/* 59D0 */be_uint32_t unknown_a9_a;
|
||||
/* 59D4 */be_uint32_t unknown_a9_b;
|
||||
/* 59D8 */be_uint16_t unknown_a9_c;
|
||||
/* 59DA */be_uint16_t unknown_a9_d;
|
||||
/* 59D0 */ be_uint32_t unknown_a9_a;
|
||||
/* 59D4 */ be_uint32_t unknown_a9_b;
|
||||
/* 59D8 */ be_uint16_t unknown_a9_c;
|
||||
/* 59DA */ be_uint16_t unknown_a9_d;
|
||||
|
||||
/* 59DC */ uint8_t unknown_a10;
|
||||
|
||||
@@ -931,8 +921,6 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
|
||||
std::string str(const DataIndex* data_index = nullptr) const;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
|
||||
struct COMDeckDefinition {
|
||||
size_t index;
|
||||
std::string player_name;
|
||||
@@ -940,8 +928,6 @@ struct COMDeckDefinition {
|
||||
parray<le_uint16_t, 0x1F> card_ids;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DataIndex {
|
||||
public:
|
||||
DataIndex(const std::string& directory, uint32_t behavior_flags);
|
||||
@@ -1004,6 +990,4 @@ private:
|
||||
std::unordered_map<std::string, std::shared_ptr<COMDeckDefinition>> com_decks_by_name;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
@@ -4,8 +4,6 @@ using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
NameEntry::NameEntry() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -17,8 +15,6 @@ void NameEntry::clear() {
|
||||
this->unused = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DeckEntry::DeckEntry() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -32,8 +28,6 @@ void DeckEntry::clear() {
|
||||
this->card_ids.clear(0xFFFF);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t index_for_card_ref(uint16_t card_ref) {
|
||||
return card_ref & 0xFF;
|
||||
}
|
||||
@@ -42,8 +36,6 @@ uint8_t client_id_for_card_ref(uint16_t card_ref) {
|
||||
return (card_ref >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t DeckState::num_drawable_cards() const {
|
||||
return this->card_refs.size() - this->draw_index;
|
||||
}
|
||||
@@ -102,8 +94,8 @@ bool DeckState::draw_card_by_ref(uint16_t card_ref) {
|
||||
this->entries[index].state = CardState::IN_HAND;
|
||||
return true;
|
||||
|
||||
// If the card is still drawable, we need to move it so it's just in front of
|
||||
// the draw index, then immediately draw it
|
||||
// If the card is still drawable, we need to move it so it's just in front of
|
||||
// the draw index, then immediately draw it
|
||||
} else if (this->entries[index].state == CardState::DRAWABLE) {
|
||||
ssize_t ref_index;
|
||||
for (ref_index = this->card_refs.size(); ref_index >= 0; ref_index--) {
|
||||
@@ -281,6 +273,4 @@ void DeckState::shuffle() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
@@ -4,13 +4,11 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "../Text.hh"
|
||||
#include "../PSOEncryption.hh"
|
||||
#include "../Text.hh"
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
struct NameEntry {
|
||||
parray<char, 0x10> name;
|
||||
uint8_t client_id;
|
||||
@@ -57,12 +55,12 @@ public:
|
||||
uint8_t client_id,
|
||||
const parray<CardIDT, 0x1F>& card_ids,
|
||||
std::shared_ptr<PSOV2Encryption> random_crypt)
|
||||
: client_id(client_id),
|
||||
draw_index(1),
|
||||
card_ref_base(this->client_id << 8),
|
||||
shuffle_enabled(true),
|
||||
loop_enabled(true),
|
||||
random_crypt(random_crypt) {
|
||||
: client_id(client_id),
|
||||
draw_index(1),
|
||||
card_ref_base(this->client_id << 8),
|
||||
shuffle_enabled(true),
|
||||
loop_enabled(true),
|
||||
random_crypt(random_crypt) {
|
||||
for (size_t z = 0; z < card_ids.size(); z++) {
|
||||
auto& e = this->entries[z];
|
||||
e.card_id = card_ids[z];
|
||||
@@ -112,6 +110,4 @@ private:
|
||||
std::shared_ptr<PSOV2Encryption> random_crypt;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
@@ -4,8 +4,6 @@ using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
MapState::MapState() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -32,8 +30,6 @@ void MapState::print(FILE* stream) const {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
MapAndRulesState::MapAndRulesState() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -54,8 +50,6 @@ void MapAndRulesState::clear() {
|
||||
this->unused5 = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool MapAndRulesState::loc_is_within_bounds(uint8_t x, uint8_t y) const {
|
||||
return (x < this->map.width) && (y < this->map.height);
|
||||
}
|
||||
@@ -75,8 +69,6 @@ void MapAndRulesState::clear_occupied_bit_for_tile(uint8_t x, uint8_t y) {
|
||||
this->map.tiles[y][x] &= 0xEF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
OverlayState::OverlayState() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -90,6 +82,4 @@ void OverlayState::clear() {
|
||||
this->unused3.clear(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
struct MapState {
|
||||
le_uint16_t width;
|
||||
le_uint16_t height;
|
||||
@@ -58,6 +56,4 @@ struct OverlayState {
|
||||
void clear();
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
+33
-36
@@ -6,40 +6,38 @@ using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
PlayerState::PlayerState(uint8_t client_id, shared_ptr<Server> server)
|
||||
: w_server(server),
|
||||
client_id(client_id),
|
||||
num_mulligans_allowed(1),
|
||||
sc_card_type(CardType::HUNTERS_SC),
|
||||
team_id(0xFF),
|
||||
atk_points(0),
|
||||
def_points(0),
|
||||
atk_points2(0),
|
||||
atk_points2_max(6),
|
||||
atk_bonuses(0),
|
||||
def_bonuses(0),
|
||||
dice_results(0),
|
||||
unknown_a4(2),
|
||||
dice_max(6),
|
||||
total_set_cards_cost(0),
|
||||
sc_card_id(0xFFFF),
|
||||
sc_card_ref(0xFFFF),
|
||||
card_refs(0xFFFF),
|
||||
discard_log_card_refs(0xFFFF),
|
||||
discard_log_reasons(0),
|
||||
assist_remaining_turns(0),
|
||||
assist_card_set_number(0),
|
||||
set_assist_card_id(0xFFFF),
|
||||
god_whim_can_use_hidden_cards(false),
|
||||
unknown_a14(0),
|
||||
assist_flags(0),
|
||||
assist_delay_turns(0),
|
||||
start_facing_direction(Direction::RIGHT),
|
||||
num_destroyed_fcs(0),
|
||||
unknown_a16(0),
|
||||
unknown_a17(0) { }
|
||||
: w_server(server),
|
||||
client_id(client_id),
|
||||
num_mulligans_allowed(1),
|
||||
sc_card_type(CardType::HUNTERS_SC),
|
||||
team_id(0xFF),
|
||||
atk_points(0),
|
||||
def_points(0),
|
||||
atk_points2(0),
|
||||
atk_points2_max(6),
|
||||
atk_bonuses(0),
|
||||
def_bonuses(0),
|
||||
dice_results(0),
|
||||
unknown_a4(2),
|
||||
dice_max(6),
|
||||
total_set_cards_cost(0),
|
||||
sc_card_id(0xFFFF),
|
||||
sc_card_ref(0xFFFF),
|
||||
card_refs(0xFFFF),
|
||||
discard_log_card_refs(0xFFFF),
|
||||
discard_log_reasons(0),
|
||||
assist_remaining_turns(0),
|
||||
assist_card_set_number(0),
|
||||
set_assist_card_id(0xFFFF),
|
||||
god_whim_can_use_hidden_cards(false),
|
||||
unknown_a14(0),
|
||||
assist_flags(0),
|
||||
assist_delay_turns(0),
|
||||
start_facing_direction(Direction::RIGHT),
|
||||
num_destroyed_fcs(0),
|
||||
unknown_a16(0),
|
||||
unknown_a17(0) {}
|
||||
|
||||
void PlayerState::init() {
|
||||
if (this->server()->player_states[this->client_id].get() != this) {
|
||||
@@ -1411,7 +1409,8 @@ void PlayerState::update_hand_and_equip_state_and_send_6xB4x02_if_needed(
|
||||
cmd.state.sc_card_ref = this->sc_card_ref;
|
||||
cmd.state.assist_card_ref2 = this->card_refs[6];
|
||||
cmd.state.assist_card_set_number = (this->card_refs[6] == 0xFFFF)
|
||||
? 0 : this->assist_card_set_number;
|
||||
? 0
|
||||
: this->assist_card_set_number;
|
||||
cmd.state.assist_card_id = this->set_assist_card_id;
|
||||
cmd.state.assist_remaining_turns = this->assist_remaining_turns;
|
||||
cmd.state.assist_delay_turns = this->assist_delay_turns;
|
||||
@@ -1830,6 +1829,4 @@ void PlayerState::compute_team_dice_boost_after_draw_phase() {
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
@@ -5,15 +5,13 @@
|
||||
#include <memory>
|
||||
|
||||
#include "../Text.hh"
|
||||
#include "DataIndex.hh"
|
||||
#include "Card.hh"
|
||||
#include "DataIndex.hh"
|
||||
#include "DeckState.hh"
|
||||
#include "PlayerStateSubordinates.hh"
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
class ServerBase;
|
||||
class Server;
|
||||
|
||||
@@ -25,8 +23,7 @@ public:
|
||||
std::shared_ptr<const Server> server() const;
|
||||
|
||||
bool draw_cards_allowed() const;
|
||||
void apply_assist_card_effect_on_set(
|
||||
std::shared_ptr<PlayerState> setter_ps);
|
||||
void apply_assist_card_effect_on_set(std::shared_ptr<PlayerState> setter_ps);
|
||||
void apply_dice_effects();
|
||||
uint16_t card_ref_for_hand_index(size_t hand_index) const;
|
||||
int16_t compute_attack_or_defense_atk_costs(const ActionState& pa) const;
|
||||
@@ -188,6 +185,4 @@ public:
|
||||
PlayerStats stats;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
@@ -6,8 +6,6 @@ using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
template <size_t Count>
|
||||
std::string string_for_refs(const parray<le_uint16_t, Count>& card_refs) {
|
||||
string ret = "[";
|
||||
@@ -24,26 +22,24 @@ std::string string_for_refs(const parray<le_uint16_t, Count>& card_refs) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Condition::Condition() {
|
||||
this->clear();
|
||||
}
|
||||
|
||||
bool Condition::operator==(const Condition& other) const {
|
||||
return (this->type == other.type) &&
|
||||
(this->remaining_turns == other.remaining_turns) &&
|
||||
(this->a_arg_value == other.a_arg_value) &&
|
||||
(this->dice_roll_value == other.dice_roll_value) &&
|
||||
(this->flags == other.flags) &&
|
||||
(this->card_definition_effect_index == other.card_definition_effect_index) &&
|
||||
(this->card_ref == other.card_ref) &&
|
||||
(this->value == other.value) &&
|
||||
(this->condition_giver_card_ref == other.condition_giver_card_ref) &&
|
||||
(this->random_percent == other.random_percent) &&
|
||||
(this->value8 == other.value8) &&
|
||||
(this->order == other.order) &&
|
||||
(this->unknown_a8 == other.unknown_a8);
|
||||
(this->remaining_turns == other.remaining_turns) &&
|
||||
(this->a_arg_value == other.a_arg_value) &&
|
||||
(this->dice_roll_value == other.dice_roll_value) &&
|
||||
(this->flags == other.flags) &&
|
||||
(this->card_definition_effect_index == other.card_definition_effect_index) &&
|
||||
(this->card_ref == other.card_ref) &&
|
||||
(this->value == other.value) &&
|
||||
(this->condition_giver_card_ref == other.condition_giver_card_ref) &&
|
||||
(this->random_percent == other.random_percent) &&
|
||||
(this->value8 == other.value8) &&
|
||||
(this->order == other.order) &&
|
||||
(this->unknown_a8 == other.unknown_a8);
|
||||
}
|
||||
bool Condition::operator!=(const Condition& other) const {
|
||||
return !this->operator==(other);
|
||||
@@ -84,8 +80,8 @@ void Condition::clear_FF() {
|
||||
std::string Condition::str() const {
|
||||
return string_printf(
|
||||
"Condition[type=%s, turns=%hhu, a_arg=%hhd, dice=%hhu, flags=%02hhX, "
|
||||
"def_eff_index=%hhu, ref=@%04hX, value=%hd, giver_ref=@%04hX "
|
||||
"percent=%hhu value8=%hd order=%hu a8=%hu]",
|
||||
"def_eff_index=%hhu, ref=@%04hX, value=%hd, giver_ref=@%04hX "
|
||||
"percent=%hhu value8=%hd order=%hu a8=%hu]",
|
||||
name_for_condition_type(this->type),
|
||||
this->remaining_turns,
|
||||
this->a_arg_value,
|
||||
@@ -101,8 +97,6 @@ std::string Condition::str() const {
|
||||
this->unknown_a8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
EffectResult::EffectResult() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -123,8 +117,8 @@ void EffectResult::clear() {
|
||||
std::string EffectResult::str() const {
|
||||
return string_printf(
|
||||
"EffectResult[att_ref=@%04hX, target_ref=@%04hX, value=%hhd, "
|
||||
"cur_hp=%hhd, ap=%hhd, tp=%hhd, flags=%02hhX, op=%hhd, "
|
||||
"cond_index=%hhu, dice=%hhu]",
|
||||
"cur_hp=%hhd, ap=%hhd, tp=%hhd, flags=%02hhX, op=%hhd, "
|
||||
"cond_index=%hhu, dice=%hhu]",
|
||||
this->attacker_card_ref.load(),
|
||||
this->target_card_ref.load(),
|
||||
this->value,
|
||||
@@ -137,20 +131,18 @@ std::string EffectResult::str() const {
|
||||
this->dice_roll_value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
CardShortStatus::CardShortStatus() {
|
||||
this->clear();
|
||||
}
|
||||
|
||||
bool CardShortStatus::operator==(const CardShortStatus& other) const {
|
||||
return (this->card_ref == other.card_ref) &&
|
||||
(this->current_hp == other.current_hp) &&
|
||||
(this->card_flags == other.card_flags) &&
|
||||
(this->loc == other.loc) &&
|
||||
(this->unused1 == other.unused1) &&
|
||||
(this->max_hp == other.max_hp) &&
|
||||
(this->unused2 == other.unused2);
|
||||
(this->current_hp == other.current_hp) &&
|
||||
(this->card_flags == other.card_flags) &&
|
||||
(this->loc == other.loc) &&
|
||||
(this->unused1 == other.unused1) &&
|
||||
(this->max_hp == other.max_hp) &&
|
||||
(this->unused2 == other.unused2);
|
||||
}
|
||||
bool CardShortStatus::operator!=(const CardShortStatus& other) const {
|
||||
return !this->operator==(other);
|
||||
@@ -160,7 +152,7 @@ std::string CardShortStatus::str() const {
|
||||
string loc_s = this->loc.str();
|
||||
return string_printf(
|
||||
"CardShortStatus[ref=@%04hX, cur_hp=%hd, flags=%08" PRIX32 ", loc=%s, "
|
||||
"u1=%04hX, max_hp=%hhd, u2=%hhu]",
|
||||
"u1=%04hX, max_hp=%hhd, u2=%hhu]",
|
||||
this->card_ref.load(),
|
||||
this->current_hp.load(),
|
||||
this->card_flags.load(),
|
||||
@@ -190,8 +182,6 @@ void CardShortStatus::clear_FF() {
|
||||
this->unused2 = 0xFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ActionState::ActionState() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -212,8 +202,8 @@ std::string ActionState::str() const {
|
||||
string action_refs_s = string_for_refs(this->action_card_refs);
|
||||
return string_printf(
|
||||
"ActionState[client=%hu, u=%hhu, facing=%s, attacker_ref=@%04hX, "
|
||||
"def_ref=@%04hX, target_refs=%s, action_refs=%s, "
|
||||
"orig_attacker_ref=@%04hX]",
|
||||
"def_ref=@%04hX, target_refs=%s, action_refs=%s, "
|
||||
"orig_attacker_ref=@%04hX]",
|
||||
this->client_id.load(),
|
||||
this->unused,
|
||||
name_for_direction(this->facing_direction),
|
||||
@@ -224,34 +214,32 @@ std::string ActionState::str() const {
|
||||
this->original_attacker_card_ref.load());
|
||||
}
|
||||
|
||||
|
||||
|
||||
ActionChain::ActionChain() {
|
||||
this->clear();
|
||||
}
|
||||
|
||||
bool ActionChain::operator==(const ActionChain& other) const {
|
||||
return (this->effective_ap == other.effective_ap) &&
|
||||
(this->effective_tp == other.effective_tp) &&
|
||||
(this->ap_effect_bonus == other.ap_effect_bonus) &&
|
||||
(this->damage == other.damage) &&
|
||||
(this->acting_card_ref == other.acting_card_ref) &&
|
||||
(this->unknown_card_ref_a3 == other.unknown_card_ref_a3) &&
|
||||
(this->attack_action_card_refs == other.attack_action_card_refs) &&
|
||||
(this->attack_action_card_ref_count == other.attack_action_card_ref_count) &&
|
||||
(this->attack_medium == other.attack_medium) &&
|
||||
(this->target_card_ref_count == other.target_card_ref_count) &&
|
||||
(this->action_subphase == other.action_subphase) &&
|
||||
(this->strike_count == other.strike_count) &&
|
||||
(this->damage_multiplier == other.damage_multiplier) &&
|
||||
(this->attack_number == other.attack_number) &&
|
||||
(this->tp_effect_bonus == other.tp_effect_bonus) &&
|
||||
(this->unused1 == other.unused1) &&
|
||||
(this->unused2 == other.unused2) &&
|
||||
(this->card_ap == other.card_ap) &&
|
||||
(this->card_tp == other.card_tp) &&
|
||||
(this->flags == other.flags) &&
|
||||
(this->target_card_refs == other.target_card_refs);
|
||||
(this->effective_tp == other.effective_tp) &&
|
||||
(this->ap_effect_bonus == other.ap_effect_bonus) &&
|
||||
(this->damage == other.damage) &&
|
||||
(this->acting_card_ref == other.acting_card_ref) &&
|
||||
(this->unknown_card_ref_a3 == other.unknown_card_ref_a3) &&
|
||||
(this->attack_action_card_refs == other.attack_action_card_refs) &&
|
||||
(this->attack_action_card_ref_count == other.attack_action_card_ref_count) &&
|
||||
(this->attack_medium == other.attack_medium) &&
|
||||
(this->target_card_ref_count == other.target_card_ref_count) &&
|
||||
(this->action_subphase == other.action_subphase) &&
|
||||
(this->strike_count == other.strike_count) &&
|
||||
(this->damage_multiplier == other.damage_multiplier) &&
|
||||
(this->attack_number == other.attack_number) &&
|
||||
(this->tp_effect_bonus == other.tp_effect_bonus) &&
|
||||
(this->unused1 == other.unused1) &&
|
||||
(this->unused2 == other.unused2) &&
|
||||
(this->card_ap == other.card_ap) &&
|
||||
(this->card_tp == other.card_tp) &&
|
||||
(this->flags == other.flags) &&
|
||||
(this->target_card_refs == other.target_card_refs);
|
||||
}
|
||||
bool ActionChain::operator!=(const ActionChain& other) const {
|
||||
return !this->operator==(other);
|
||||
@@ -262,12 +250,12 @@ std::string ActionChain::str() const {
|
||||
string target_card_refs_s = string_for_refs(this->target_card_refs);
|
||||
return string_printf(
|
||||
"ActionChain[eff_ap=%hhd, eff_tp=%hhd, ap_bonus=%hhd, damage=%hhd, "
|
||||
"acting_ref=@%04hX, unknown_ref_a3=@%04hX, "
|
||||
"attack_action_refs=%s, attack_action_ref_count=%hhu, "
|
||||
"medium=%s, target_ref_count=%hhu, subphase=%s, "
|
||||
"strikes=%hhu, damage_mult=%hhd, attack_num=%hhu, "
|
||||
"tp_bonus=%hhd, u1=%hhu, u2=%hhu, card_ap=%hhd, "
|
||||
"card_tp=%hhd, flags=%08" PRIX32 ", target_refs=%s]",
|
||||
"acting_ref=@%04hX, unknown_ref_a3=@%04hX, "
|
||||
"attack_action_refs=%s, attack_action_ref_count=%hhu, "
|
||||
"medium=%s, target_ref_count=%hhu, subphase=%s, "
|
||||
"strikes=%hhu, damage_mult=%hhd, attack_num=%hhu, "
|
||||
"tp_bonus=%hhd, u1=%hhu, u2=%hhu, card_ap=%hhd, "
|
||||
"card_tp=%hhd, flags=%08" PRIX32 ", target_refs=%s]",
|
||||
this->effective_ap,
|
||||
this->effective_tp,
|
||||
this->ap_effect_bonus,
|
||||
@@ -339,8 +327,6 @@ void ActionChain::clear_FF() {
|
||||
this->target_card_refs.clear(0xFFFF);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ActionChainWithConds::ActionChainWithConds() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -495,24 +481,22 @@ bool ActionChainWithConds::unknown_8024DEC4() const {
|
||||
return this->check_flag(4) ? false : (this->chain.target_card_ref_count != 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ActionMetadata::ActionMetadata() {
|
||||
this->clear();
|
||||
}
|
||||
|
||||
bool ActionMetadata::operator==(const ActionMetadata& other) const {
|
||||
return (this->card_ref == other.card_ref) &&
|
||||
(this->target_card_ref_count == other.target_card_ref_count) &&
|
||||
(this->defense_card_ref_count == other.defense_card_ref_count) &&
|
||||
(this->action_subphase == other.action_subphase) &&
|
||||
(this->defense_power == other.defense_power) &&
|
||||
(this->defense_bonus == other.defense_bonus) &&
|
||||
(this->attack_bonus == other.attack_bonus) &&
|
||||
(this->flags == other.flags) &&
|
||||
(this->target_card_refs == other.target_card_refs) &&
|
||||
(this->defense_card_refs == other.defense_card_refs) &&
|
||||
(this->original_attacker_card_refs == other.original_attacker_card_refs);
|
||||
(this->target_card_ref_count == other.target_card_ref_count) &&
|
||||
(this->defense_card_ref_count == other.defense_card_ref_count) &&
|
||||
(this->action_subphase == other.action_subphase) &&
|
||||
(this->defense_power == other.defense_power) &&
|
||||
(this->defense_bonus == other.defense_bonus) &&
|
||||
(this->attack_bonus == other.attack_bonus) &&
|
||||
(this->flags == other.flags) &&
|
||||
(this->target_card_refs == other.target_card_refs) &&
|
||||
(this->defense_card_refs == other.defense_card_refs) &&
|
||||
(this->original_attacker_card_refs == other.original_attacker_card_refs);
|
||||
}
|
||||
bool ActionMetadata::operator!=(const ActionMetadata& other) const {
|
||||
return !this->operator==(other);
|
||||
@@ -524,9 +508,9 @@ std::string ActionMetadata::str() const {
|
||||
string original_attacker_card_refs_s = string_for_refs(this->original_attacker_card_refs);
|
||||
return string_printf(
|
||||
"ActionMetadata[ref=@%04hX, target_ref_count=%hhu, def_ref_count=%hhu, "
|
||||
"subphase=%s, def_power=%hhd, def_bonus=%hhd, "
|
||||
"att_bonus=%hhd, flags=%08" PRIX32 ", target_refs=%s, "
|
||||
"defense_refs=%s, original_attacker_refs=%s]",
|
||||
"subphase=%s, def_power=%hhd, def_bonus=%hhd, "
|
||||
"att_bonus=%hhd, flags=%08" PRIX32 ", target_refs=%s, "
|
||||
"defense_refs=%s, original_attacker_refs=%s]",
|
||||
this->card_ref.load(),
|
||||
this->target_card_ref_count,
|
||||
this->defense_card_ref_count,
|
||||
@@ -610,8 +594,6 @@ void ActionMetadata::add_defense_card_ref(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
HandAndEquipState::HandAndEquipState() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -623,13 +605,13 @@ std::string HandAndEquipState::str() const {
|
||||
string set_card_refs2_s = string_for_refs(this->set_card_refs2);
|
||||
return string_printf(
|
||||
"HandAndEquipState[dice=[%hhu, %hhu], atk=%hhu, def=%hhu, atk2=%hhu, "
|
||||
"a1=%hhu, total_set_cost=%hhu, is_cpu=%hhu, "
|
||||
"assist_flags=%08" PRIX32 ", hand_refs=%s, "
|
||||
"assist_ref=@%04hX, set_refs=%s, sc_ref=@%04hX, "
|
||||
"hand_refs2=%s, set_refs2=%s, assist_ref2=@%04hX, "
|
||||
"assist_set_num=%hu, assist_card_id=%04hX, "
|
||||
"assist_turns=%hhu, assit_dely=%hhu, atk_bonus=%hhu, "
|
||||
"def_bonus=%hhu, u2=[%hhu, %hhu]]",
|
||||
"a1=%hhu, total_set_cost=%hhu, is_cpu=%hhu, "
|
||||
"assist_flags=%08" PRIX32 ", hand_refs=%s, "
|
||||
"assist_ref=@%04hX, set_refs=%s, sc_ref=@%04hX, "
|
||||
"hand_refs2=%s, set_refs2=%s, assist_ref2=@%04hX, "
|
||||
"assist_set_num=%hu, assist_card_id=%04hX, "
|
||||
"assist_turns=%hhu, assit_dely=%hhu, atk_bonus=%hhu, "
|
||||
"def_bonus=%hhu, u2=[%hhu, %hhu]]",
|
||||
this->dice_results[0],
|
||||
this->dice_results[1],
|
||||
this->atk_points,
|
||||
@@ -706,8 +688,6 @@ void HandAndEquipState::clear_FF() {
|
||||
this->unused2.clear(0xFF);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PlayerStats::PlayerStats() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -747,12 +727,7 @@ float PlayerStats::score(size_t num_rounds) const {
|
||||
// Ep3 PsoV3.dol, so it's presumably correct. Is the PSO-World formula simply
|
||||
// incorrect, or is it from e.g. the Japanese version, which may have a
|
||||
// different rank calculation function?
|
||||
return 38.0f
|
||||
+ 0.8f * this->action_card_negated_damage
|
||||
- 2.3f * num_rounds
|
||||
- 1.8f * this->sc_damage_taken
|
||||
+ 3.0f * this->max_attack_combo_size
|
||||
+ (this->damage_given - this->damage_taken);
|
||||
return 38.0f + 0.8f * this->action_card_negated_damage - 2.3f * num_rounds - 1.8f * this->sc_damage_taken + 3.0f * this->max_attack_combo_size + (this->damage_given - this->damage_taken);
|
||||
}
|
||||
|
||||
uint8_t PlayerStats::rank(size_t num_rounds) const {
|
||||
@@ -767,7 +742,7 @@ constexpr size_t RANK_THRESHOLD_COUNT = 9;
|
||||
static const float RANK_THRESHOLDS[RANK_THRESHOLD_COUNT] = {
|
||||
15.0f, 25.0f, 30.0f, 40.0f, 50.0f, 60.0f, 65.0f, 75.0f, 85.0f};
|
||||
static const char* RANK_NAMES[RANK_THRESHOLD_COUNT + 1] = {
|
||||
"E", "D", "D+", "C", "C+", "B", "B+", "A", "A+", "S"};
|
||||
"E", "D", "D+", "C", "C+", "B", "B+", "A", "A+", "S"};
|
||||
|
||||
uint8_t PlayerStats::rank_for_score(float score) {
|
||||
size_t rank = 0;
|
||||
@@ -784,9 +759,6 @@ const char* PlayerStats::name_for_rank(uint8_t rank) {
|
||||
return RANK_NAMES[rank];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool is_card_within_range(
|
||||
const parray<uint8_t, 9 * 9>& range,
|
||||
const Location& anchor_loc,
|
||||
@@ -824,6 +796,4 @@ vector<uint16_t> get_card_refs_within_range(
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
class ServerBase;
|
||||
class Server;
|
||||
class Card;
|
||||
@@ -269,13 +267,9 @@ struct PlayerStats {
|
||||
static const char* name_for_rank(uint8_t rank);
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
|
||||
std::vector<uint16_t> get_card_refs_within_range(
|
||||
const parray<uint8_t, 9 * 9>& range,
|
||||
const Location& loc,
|
||||
const parray<CardShortStatus, 0x10>& short_statuses);
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
+223
-228
@@ -6,8 +6,6 @@ using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
void compute_effective_range(
|
||||
parray<uint8_t, 9 * 9>& ret,
|
||||
shared_ptr<const DataIndex> data_index,
|
||||
@@ -189,14 +187,12 @@ bool card_linkage_is_valid(
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
RulerServer::RulerServer(shared_ptr<Server> server)
|
||||
: w_server(server),
|
||||
team_id_for_client_id(0xFF),
|
||||
error_code1(0),
|
||||
error_code2(0),
|
||||
error_code3(0) { }
|
||||
: w_server(server),
|
||||
team_id_for_client_id(0xFF),
|
||||
error_code1(0),
|
||||
error_code2(0),
|
||||
error_code3(0) {}
|
||||
|
||||
shared_ptr<Server> RulerServer::server() {
|
||||
auto s = this->w_server.lock();
|
||||
@@ -318,11 +314,11 @@ bool RulerServer::attack_action_has_rampage_and_not_pierce(
|
||||
auto attack_medium = this->get_attack_medium(pa);
|
||||
|
||||
if (!this->compute_effective_range_and_target_mode_for_attack(
|
||||
pa, &effective_range_card_id, &effective_target_mode, &orig_card_ref)) {
|
||||
pa, &effective_range_card_id, &effective_target_mode, &orig_card_ref)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((orig_card_ref != 0xFFFF) && (orig_card_ref != pa.attacker_card_ref) &&
|
||||
if ((orig_card_ref != 0xFFFF) && (orig_card_ref != pa.attacker_card_ref) &&
|
||||
!this->check_usability_or_apply_condition_for_card_refs(
|
||||
orig_card_ref, pa.attacker_card_ref, card_ref, 0xFF, AttackMedium::INVALID_FF)) {
|
||||
return false;
|
||||
@@ -426,9 +422,9 @@ bool RulerServer::attack_action_has_pierce_and_not_rampage(
|
||||
for (; last_cond_index >= 0; last_cond_index--) {
|
||||
bool has_rampage = false;
|
||||
if (this->card_has_pierce_or_rampage(
|
||||
client_id, ce->def.effects[last_cond_index].type, &has_rampage,
|
||||
pa.attacker_card_ref, pa.action_card_refs[last_action_card_index],
|
||||
last_cond_index, attack_medium)) {
|
||||
client_id, ce->def.effects[last_cond_index].type, &has_rampage,
|
||||
pa.attacker_card_ref, pa.action_card_refs[last_action_card_index],
|
||||
last_cond_index, attack_medium)) {
|
||||
return true;
|
||||
}
|
||||
if (has_rampage) {
|
||||
@@ -442,10 +438,10 @@ bool RulerServer::attack_action_has_pierce_and_not_rampage(
|
||||
for (ssize_t cond_index = 8; cond_index >= 0; cond_index--) {
|
||||
bool has_rampage = false;
|
||||
if (this->card_has_pierce_or_rampage(
|
||||
client_id, chain->conditions[cond_index].type, &has_rampage,
|
||||
pa.attacker_card_ref, chain->conditions[cond_index].card_ref,
|
||||
chain->conditions[cond_index].card_definition_effect_index,
|
||||
attack_medium)) {
|
||||
client_id, chain->conditions[cond_index].type, &has_rampage,
|
||||
pa.attacker_card_ref, chain->conditions[cond_index].card_ref,
|
||||
chain->conditions[cond_index].card_definition_effect_index,
|
||||
attack_medium)) {
|
||||
return true;
|
||||
}
|
||||
if (has_rampage) {
|
||||
@@ -457,7 +453,6 @@ bool RulerServer::attack_action_has_pierce_and_not_rampage(
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool RulerServer::card_exists_by_status(const CardShortStatus& stat) const {
|
||||
if ((stat.card_flags & 3) || (stat.card_ref == 0xFFFF)) {
|
||||
return false;
|
||||
@@ -494,10 +489,10 @@ bool RulerServer::card_id_is_boss_sc(uint16_t card_id) {
|
||||
|
||||
bool RulerServer::card_id_is_support_tech_or_support_pb(uint16_t card_id) {
|
||||
return (card_id == 0x00E1) ||
|
||||
(card_id == 0x00E2) ||
|
||||
(card_id == 0x00E6) ||
|
||||
(card_id == 0x00EB) ||
|
||||
(card_id == 0x00EC);
|
||||
(card_id == 0x00E2) ||
|
||||
(card_id == 0x00E6) ||
|
||||
(card_id == 0x00EB) ||
|
||||
(card_id == 0x00EC);
|
||||
}
|
||||
|
||||
bool RulerServer::card_ref_can_attack(uint16_t card_ref) {
|
||||
@@ -537,11 +532,11 @@ bool RulerServer::card_ref_can_attack(uint16_t card_ref) {
|
||||
// then the item also cannot attack
|
||||
if ((ce->def.type == CardType::ITEM) &&
|
||||
(!this->short_statuses[client_id] ||
|
||||
(this->short_statuses[client_id]->at(0).card_ref == 0xFFFF) ||
|
||||
this->find_condition_on_card_ref(this->short_statuses[client_id]->at(0).card_ref, ConditionType::HOLD) ||
|
||||
this->find_condition_on_card_ref(this->short_statuses[client_id]->at(0).card_ref, ConditionType::GUOM) ||
|
||||
this->find_condition_on_card_ref(this->short_statuses[client_id]->at(0).card_ref, ConditionType::PARALYZE) ||
|
||||
this->find_condition_on_card_ref(this->short_statuses[client_id]->at(0).card_ref, ConditionType::FREEZE))) {
|
||||
(this->short_statuses[client_id]->at(0).card_ref == 0xFFFF) ||
|
||||
this->find_condition_on_card_ref(this->short_statuses[client_id]->at(0).card_ref, ConditionType::HOLD) ||
|
||||
this->find_condition_on_card_ref(this->short_statuses[client_id]->at(0).card_ref, ConditionType::GUOM) ||
|
||||
this->find_condition_on_card_ref(this->short_statuses[client_id]->at(0).card_ref, ConditionType::PARALYZE) ||
|
||||
this->find_condition_on_card_ref(this->short_statuses[client_id]->at(0).card_ref, ConditionType::FREEZE))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -589,7 +584,7 @@ bool RulerServer::card_ref_can_move(
|
||||
const auto& item_stat = short_statuses->at(z);
|
||||
if ((item_stat.card_ref != 0xFFFF) && this->card_exists_by_status(item_stat) &&
|
||||
(this->find_condition_on_card_ref(item_stat.card_ref, ConditionType::GUOM) ||
|
||||
this->find_condition_on_card_ref(item_stat.card_ref, ConditionType::IMMOBILE))) {
|
||||
this->find_condition_on_card_ref(item_stat.card_ref, ConditionType::IMMOBILE))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -951,11 +946,11 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
// positioning/team setup
|
||||
if (is_item_usability_check &&
|
||||
((criterion_code == CriterionCode::SAME_TEAM) ||
|
||||
(criterion_code == CriterionCode::SAME_PLAYER) ||
|
||||
(criterion_code == CriterionCode::SAME_TEAM_NOT_SAME_PLAYER) ||
|
||||
(criterion_code == CriterionCode::UNKNOWN_07) ||
|
||||
(criterion_code == CriterionCode::NOT_SC) ||
|
||||
(criterion_code == CriterionCode::SC))) {
|
||||
(criterion_code == CriterionCode::SAME_PLAYER) ||
|
||||
(criterion_code == CriterionCode::SAME_TEAM_NOT_SAME_PLAYER) ||
|
||||
(criterion_code == CriterionCode::UNKNOWN_07) ||
|
||||
(criterion_code == CriterionCode::NOT_SC) ||
|
||||
(criterion_code == CriterionCode::SC))) {
|
||||
criterion_code = CriterionCode::NONE;
|
||||
}
|
||||
|
||||
@@ -988,7 +983,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
case CriterionCode::SAME_TEAM:
|
||||
if ((client_id1 == client_id2) ||
|
||||
((client_id1 != 0xFF) && (client_id2 != 0xFF) &&
|
||||
(this->team_id_for_client_id[client_id1] == this->team_id_for_client_id[client_id2]))) {
|
||||
(this->team_id_for_client_id[client_id1] == this->team_id_for_client_id[client_id2]))) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -1026,255 +1021,255 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
break;
|
||||
case CriterionCode::HUNTER_HUMAN_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
0x0001, // Orland
|
||||
0x0002, // Kranz
|
||||
0x0003, // Ino'lis
|
||||
0x0004, // Sil'fer
|
||||
0x0006, // Kylria
|
||||
0x0111, // Relmitos
|
||||
0x0112, // Viviana
|
||||
0x0115, // Glustar
|
||||
0x02AA, // H-HUmar
|
||||
0x02AB, // H-HUnewearl
|
||||
0x02AE, // H-RAmar
|
||||
0x02AF, // H-RAmarl
|
||||
0x02B2, // H-FOmar
|
||||
0x02B3, // H-FOmarl
|
||||
0x02B4, // H-FOnewm
|
||||
0x02B5, // H-FOnewearl
|
||||
0x02CC, // H-HUmar
|
||||
0x02CD, // H-RAmarl
|
||||
0x02CE, // H-FOmarl
|
||||
0x02CF, // H-HUnewearl
|
||||
0x02D1, // H-RAmarl
|
||||
0x02D5, // H-FOmar
|
||||
0x02D6, // H-FOnewearl
|
||||
0x02D9, // H-FOnewm
|
||||
0x0001, // Orland
|
||||
0x0002, // Kranz
|
||||
0x0003, // Ino'lis
|
||||
0x0004, // Sil'fer
|
||||
0x0006, // Kylria
|
||||
0x0111, // Relmitos
|
||||
0x0112, // Viviana
|
||||
0x0115, // Glustar
|
||||
0x02AA, // H-HUmar
|
||||
0x02AB, // H-HUnewearl
|
||||
0x02AE, // H-RAmar
|
||||
0x02AF, // H-RAmarl
|
||||
0x02B2, // H-FOmar
|
||||
0x02B3, // H-FOmarl
|
||||
0x02B4, // H-FOnewm
|
||||
0x02B5, // H-FOnewearl
|
||||
0x02CC, // H-HUmar
|
||||
0x02CD, // H-RAmarl
|
||||
0x02CE, // H-FOmarl
|
||||
0x02CF, // H-HUnewearl
|
||||
0x02D1, // H-RAmarl
|
||||
0x02D5, // H-FOmar
|
||||
0x02D6, // H-FOnewearl
|
||||
0x02D9, // H-FOnewm
|
||||
};
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_HU_CLASS_MALE_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
0x0001, // Orland
|
||||
0x0113, // Teifu
|
||||
0x02AA, // H-HUmar
|
||||
0x02AC, // H-HUcast
|
||||
0x02CC, // H-HUmar
|
||||
0x02D7, // H-HUcast
|
||||
0x0001, // Orland
|
||||
0x0113, // Teifu
|
||||
0x02AA, // H-HUmar
|
||||
0x02AC, // H-HUcast
|
||||
0x02CC, // H-HUmar
|
||||
0x02D7, // H-HUcast
|
||||
};
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_FEMALE_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
0x0003, // Ino'lis
|
||||
0x0004, // Sil'fer
|
||||
0x0006, // Kylria
|
||||
0x0110, // Saligun
|
||||
0x0112, // Viviana
|
||||
0x0114, // Stella
|
||||
0x02AB, // H-HUnewearl
|
||||
0x02AD, // H-HUcaseal
|
||||
0x02AF, // H-RAmarl
|
||||
0x02B1, // H-RAcaseal
|
||||
0x02B3, // H-FOmarl
|
||||
0x02B5, // H-FOnewearl
|
||||
0x02CE, // H-FOmarl
|
||||
0x02CF, // H-HUnewearl
|
||||
0x02D1, // H-RAmarl
|
||||
0x02D4, // H-HUcaseal
|
||||
0x02D6, // H-FOnewearl
|
||||
0x02D8, // H-RAcaseal
|
||||
0x0003, // Ino'lis
|
||||
0x0004, // Sil'fer
|
||||
0x0006, // Kylria
|
||||
0x0110, // Saligun
|
||||
0x0112, // Viviana
|
||||
0x0114, // Stella
|
||||
0x02AB, // H-HUnewearl
|
||||
0x02AD, // H-HUcaseal
|
||||
0x02AF, // H-RAmarl
|
||||
0x02B1, // H-RAcaseal
|
||||
0x02B3, // H-FOmarl
|
||||
0x02B5, // H-FOnewearl
|
||||
0x02CE, // H-FOmarl
|
||||
0x02CF, // H-HUnewearl
|
||||
0x02D1, // H-RAmarl
|
||||
0x02D4, // H-HUcaseal
|
||||
0x02D6, // H-FOnewearl
|
||||
0x02D8, // H-RAcaseal
|
||||
};
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_HU_OR_FO_CLASS_HUMAN_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
0x0001, // Orland
|
||||
0x0003, // Ino'lis
|
||||
0x0004, // Sil'fer
|
||||
0x0111, // Relmitos
|
||||
0x0115, // Glustar
|
||||
0x0112, // Viviana
|
||||
0x02AA, // H-HUmar
|
||||
0x02AB, // H-HUnewearl
|
||||
0x02B2, // H-FOmar
|
||||
0x02B3, // H-FOmarl
|
||||
0x02B4, // H-FOnewm
|
||||
0x02B5, // H-FOnewearl
|
||||
0x02CC, // H-HUmar
|
||||
0x02CE, // H-FOmarl
|
||||
0x02CF, // H-HUnewearl
|
||||
0x02D5, // H-FOmar
|
||||
0x02D6, // H-FOnewearl
|
||||
0x02D9, // H-FOnewm
|
||||
0x0001, // Orland
|
||||
0x0003, // Ino'lis
|
||||
0x0004, // Sil'fer
|
||||
0x0111, // Relmitos
|
||||
0x0115, // Glustar
|
||||
0x0112, // Viviana
|
||||
0x02AA, // H-HUmar
|
||||
0x02AB, // H-HUnewearl
|
||||
0x02B2, // H-FOmar
|
||||
0x02B3, // H-FOmarl
|
||||
0x02B4, // H-FOnewm
|
||||
0x02B5, // H-FOnewearl
|
||||
0x02CC, // H-HUmar
|
||||
0x02CE, // H-FOmarl
|
||||
0x02CF, // H-HUnewearl
|
||||
0x02D5, // H-FOmar
|
||||
0x02D6, // H-FOnewearl
|
||||
0x02D9, // H-FOnewm
|
||||
};
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_HU_CLASS_ANDROID_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
0x0110, // Saligun
|
||||
0x0113, // Teifu
|
||||
0x02AC, // H-HUcast
|
||||
0x02AD, // H-HUcaseal
|
||||
0x02D4, // H-HUcaseal
|
||||
0x02D7, // H-HUcast
|
||||
0x0110, // Saligun
|
||||
0x0113, // Teifu
|
||||
0x02AC, // H-HUcast
|
||||
0x02AD, // H-HUcaseal
|
||||
0x02D4, // H-HUcaseal
|
||||
0x02D7, // H-HUcast
|
||||
};
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::UNKNOWN_10: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
0x0001, // Orland
|
||||
0x0003, // Ino'lis
|
||||
0x0110, // Saligun
|
||||
0x0111, // Relmitos
|
||||
0x0113, // Teifu
|
||||
0x02AA, // H-HUmar
|
||||
0x02AC, // H-HUcast
|
||||
0x02AD, // H-HUcaseal
|
||||
0x02B2, // H-FOmar
|
||||
0x02B3, // H-FOmarl
|
||||
0x02CC, // H-HUmar
|
||||
0x02CE, // H-FOmarl
|
||||
0x02D4, // H-HUcaseal
|
||||
0x02D5, // H-FOmar
|
||||
0x02D7, // H-HUcast
|
||||
0x0001, // Orland
|
||||
0x0003, // Ino'lis
|
||||
0x0110, // Saligun
|
||||
0x0111, // Relmitos
|
||||
0x0113, // Teifu
|
||||
0x02AA, // H-HUmar
|
||||
0x02AC, // H-HUcast
|
||||
0x02AD, // H-HUcaseal
|
||||
0x02B2, // H-FOmar
|
||||
0x02B3, // H-FOmarl
|
||||
0x02CC, // H-HUmar
|
||||
0x02CE, // H-FOmarl
|
||||
0x02D4, // H-HUcaseal
|
||||
0x02D5, // H-FOmar
|
||||
0x02D7, // H-HUcast
|
||||
};
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::UNKNOWN_11: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
0x0001, // Orland
|
||||
0x0002, // Kranz
|
||||
0x0005, // Guykild
|
||||
0x0113, // Teifu
|
||||
0x02AA, // H-HUmar
|
||||
0x02AC, // H-HUcast
|
||||
0x02AE, // H-RAmar
|
||||
0x02B0, // H-RAcast
|
||||
0x02CC, // H-HUmar
|
||||
0x02CD, // H-RAmarl
|
||||
0x02D0, // H-RAcast
|
||||
0x02D7, // H-HUcast
|
||||
0x0001, // Orland
|
||||
0x0002, // Kranz
|
||||
0x0005, // Guykild
|
||||
0x0113, // Teifu
|
||||
0x02AA, // H-HUmar
|
||||
0x02AC, // H-HUcast
|
||||
0x02AE, // H-RAmar
|
||||
0x02B0, // H-RAcast
|
||||
0x02CC, // H-HUmar
|
||||
0x02CD, // H-RAmarl
|
||||
0x02D0, // H-RAcast
|
||||
0x02D7, // H-HUcast
|
||||
};
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_HUNEWEARL_CLASS_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
0x0004, // Sil'fer
|
||||
0x02AB, // H-HUnewearl
|
||||
0x02CF, // H-HUnewearl
|
||||
0x0004, // Sil'fer
|
||||
0x02AB, // H-HUnewearl
|
||||
0x02CF, // H-HUnewearl
|
||||
};
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_RA_CLASS_MALE_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
0x0002, // Kranz
|
||||
0x0005, // Guykild
|
||||
0x02AE, // H-RAmar
|
||||
0x02B0, // H-RAcast
|
||||
0x02CD, // H-RAmarl
|
||||
0x02D0, // H-RAcast
|
||||
0x0002, // Kranz
|
||||
0x0005, // Guykild
|
||||
0x02AE, // H-RAmar
|
||||
0x02B0, // H-RAcast
|
||||
0x02CD, // H-RAmarl
|
||||
0x02D0, // H-RAcast
|
||||
};
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_RA_CLASS_FEMALE_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
0x0006, // Kylria
|
||||
0x0114, // Stella
|
||||
0x02AF, // H-RAmarl
|
||||
0x02B1, // H-RAcaseal
|
||||
0x02D1, // H-RAmarl
|
||||
0x02D2, // D-RAcaseal
|
||||
0x0006, // Kylria
|
||||
0x0114, // Stella
|
||||
0x02AF, // H-RAmarl
|
||||
0x02B1, // H-RAcaseal
|
||||
0x02D1, // H-RAmarl
|
||||
0x02D2, // D-RAcaseal
|
||||
};
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_RA_OR_FO_CLASS_FEMALE_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
0x0003, // Ino'lis
|
||||
0x0006, // Kylria
|
||||
0x0112, // Viviana
|
||||
0x0114, // Stella
|
||||
0x02AF, // H-RAmarl
|
||||
0x02B1, // H-RAcaseal
|
||||
0x02B3, // H-FOmarl
|
||||
0x02B5, // H-FOnewearl
|
||||
0x02CE, // H-FOmarl
|
||||
0x02D1, // H-RAmarl
|
||||
0x02D6, // H-FOnewearl
|
||||
0x02D8, // H-RAcaseal
|
||||
0x0003, // Ino'lis
|
||||
0x0006, // Kylria
|
||||
0x0112, // Viviana
|
||||
0x0114, // Stella
|
||||
0x02AF, // H-RAmarl
|
||||
0x02B1, // H-RAcaseal
|
||||
0x02B3, // H-FOmarl
|
||||
0x02B5, // H-FOnewearl
|
||||
0x02CE, // H-FOmarl
|
||||
0x02D1, // H-RAmarl
|
||||
0x02D6, // H-FOnewearl
|
||||
0x02D8, // H-RAcaseal
|
||||
};
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_HU_OR_RA_CLASS_HUMAN_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
0x0001, // Orland
|
||||
0x0002, // Kranz
|
||||
0x0004, // Sil'fer
|
||||
0x0006, // Kylria
|
||||
0x02AA, // H-HUmar
|
||||
0x02AB, // H-HUnewearl
|
||||
0x02AE, // H-RAmar
|
||||
0x02AF, // H-RAmarl
|
||||
0x02CC, // H-HUmar
|
||||
0x02CD, // H-RAmarl
|
||||
0x02CF, // H-HUnewearl
|
||||
0x02D1, // H-RAmarl
|
||||
0x0001, // Orland
|
||||
0x0002, // Kranz
|
||||
0x0004, // Sil'fer
|
||||
0x0006, // Kylria
|
||||
0x02AA, // H-HUmar
|
||||
0x02AB, // H-HUnewearl
|
||||
0x02AE, // H-RAmar
|
||||
0x02AF, // H-RAmarl
|
||||
0x02CC, // H-HUmar
|
||||
0x02CD, // H-RAmarl
|
||||
0x02CF, // H-HUnewearl
|
||||
0x02D1, // H-RAmarl
|
||||
};
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_RA_CLASS_ANDROID_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
0x0005, // Guykild
|
||||
0x0114, // Stella
|
||||
0x02B0, // H-RAcast
|
||||
0x02B1, // H-RAcaseal
|
||||
0x02D0, // H-RAcast
|
||||
0x02D8, // H-RAcaseal
|
||||
0x0005, // Guykild
|
||||
0x0114, // Stella
|
||||
0x02B0, // H-RAcast
|
||||
0x02B1, // H-RAcaseal
|
||||
0x02D0, // H-RAcast
|
||||
0x02D8, // H-RAcaseal
|
||||
};
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_FO_CLASS_FEMALE_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
0x0003, // Ino'lis
|
||||
0x0112, // Viviana
|
||||
0x02B3, // H-FOmarl
|
||||
0x02B5, // H-FOnewearl
|
||||
0x02CE, // H-FOmarl
|
||||
0x02D6, // H-FOnewearl
|
||||
0x0003, // Ino'lis
|
||||
0x0112, // Viviana
|
||||
0x02B3, // H-FOmarl
|
||||
0x02B5, // H-FOnewearl
|
||||
0x02CE, // H-FOmarl
|
||||
0x02D6, // H-FOnewearl
|
||||
};
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_FEMALE_HUMAN_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
0x0003, // Ino'lis
|
||||
0x0004, // Sil'fer
|
||||
0x0006, // Kylria
|
||||
0x0112, // Viviana
|
||||
0x02AB, // H-HUnewearl
|
||||
0x02AF, // H-RAmarl
|
||||
0x02B3, // H-FOmarl
|
||||
0x02B5, // H-FOnewearl
|
||||
0x02CE, // H-FOmarl
|
||||
0x02CF, // H-HUnewearl
|
||||
0x02D1, // H-RAmarl
|
||||
0x02D6, // H-FOnewearl
|
||||
0x0003, // Ino'lis
|
||||
0x0004, // Sil'fer
|
||||
0x0006, // Kylria
|
||||
0x0112, // Viviana
|
||||
0x02AB, // H-HUnewearl
|
||||
0x02AF, // H-RAmarl
|
||||
0x02B3, // H-FOmarl
|
||||
0x02B5, // H-FOnewearl
|
||||
0x02CE, // H-FOmarl
|
||||
0x02CF, // H-HUnewearl
|
||||
0x02D1, // H-RAmarl
|
||||
0x02D6, // H-FOnewearl
|
||||
};
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_ANDROID_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
0x0005, // Guykild
|
||||
0x0110, // Saligun
|
||||
0x0113, // Teifu
|
||||
0x0114, // Stella
|
||||
0x02AC, // H-HUcast
|
||||
0x02AD, // H-HUcaseal
|
||||
0x02B0, // H-RAcast
|
||||
0x02B1, // H-RAcaseal
|
||||
0x02D0, // H-RAcast
|
||||
0x02D4, // H-HUcaseal
|
||||
0x02D7, // H-HUcast
|
||||
0x02D8, // H-RAcaseal
|
||||
0x0005, // Guykild
|
||||
0x0110, // Saligun
|
||||
0x0113, // Teifu
|
||||
0x0114, // Stella
|
||||
0x02AC, // H-HUcast
|
||||
0x02AD, // H-HUcaseal
|
||||
0x02B0, // H-RAcast
|
||||
0x02B1, // H-RAcaseal
|
||||
0x02D0, // H-RAcast
|
||||
0x02D4, // H-HUcaseal
|
||||
0x02D7, // H-HUcast
|
||||
0x02D8, // H-RAcaseal
|
||||
};
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
@@ -1368,7 +1363,7 @@ uint16_t RulerServer::compute_attack_or_defense_costs(
|
||||
|
||||
if (((action_type == ActionType::ATTACK) || (action_type == ActionType::INVALID_00)) &&
|
||||
(this->find_condition_on_card_ref(pa.attacker_card_ref, ConditionType::BIG_SWING) ||
|
||||
this->find_condition_on_card_ref(sc_card_ref_if_item, ConditionType::BIG_SWING))) {
|
||||
this->find_condition_on_card_ref(sc_card_ref_if_item, ConditionType::BIG_SWING))) {
|
||||
cost_bias++;
|
||||
}
|
||||
|
||||
@@ -1435,7 +1430,8 @@ bool RulerServer::compute_effective_range_and_target_mode_for_attack(
|
||||
TargetMode* out_effective_target_mode,
|
||||
uint16_t* out_orig_card_ref) const {
|
||||
size_t z;
|
||||
for (z = 0; (z < 9) && (pa.action_card_refs[z] != 0xFFFF); z++) { }
|
||||
for (z = 0; (z < 9) && (pa.action_card_refs[z] != 0xFFFF); z++) {
|
||||
}
|
||||
if (z >= 9) {
|
||||
return false;
|
||||
}
|
||||
@@ -1705,7 +1701,7 @@ int32_t RulerServer::error_code_for_client_setting_card(
|
||||
if ((short_statuses->at(0).card_ref == 0xFFFF) ||
|
||||
!this->card_exists_by_status(short_statuses->at(0)) ||
|
||||
!this->check_usability_or_apply_condition_for_card_refs(
|
||||
card_ref, short_statuses->at(0).card_ref, 0xFFFF, 0xFF, AttackMedium::INVALID_FF)) {
|
||||
card_ref, short_statuses->at(0).card_ref, 0xFFFF, 0xFF, AttackMedium::INVALID_FF)) {
|
||||
return -0x75;
|
||||
}
|
||||
|
||||
@@ -1764,7 +1760,7 @@ int32_t RulerServer::error_code_for_client_setting_card(
|
||||
Location summon_area_loc;
|
||||
uint8_t summon_area_size;
|
||||
if (!this->get_creature_summon_area(
|
||||
client_id, &summon_area_loc, &summon_area_size)) {
|
||||
client_id, &summon_area_loc, &summon_area_size)) {
|
||||
if (team_id != 1) {
|
||||
if ((loc->x > 0) && (loc->x < this->map_and_rules->map.width - 1)) {
|
||||
if ((loc->y < this->map_and_rules->map.height - summon_cost - 1) &&
|
||||
@@ -1984,7 +1980,8 @@ shared_ptr<const DataIndex::CardEntry> RulerServer::definition_for_card_id(
|
||||
uint32_t RulerServer::get_card_id_with_effective_range(
|
||||
uint16_t card_ref, uint16_t card_id_override, TargetMode* out_target_mode) const {
|
||||
uint16_t card_id = (card_id_override == 0xFFFF)
|
||||
? this->card_id_for_card_ref(card_ref) : card_id_override;
|
||||
? this->card_id_for_card_ref(card_ref)
|
||||
: card_id_override;
|
||||
|
||||
if (card_id != 0xFFFF) {
|
||||
auto ce = this->definition_for_card_id(card_id);
|
||||
@@ -2102,7 +2099,7 @@ bool RulerServer::get_move_path_length_and_cost(
|
||||
parray<uint8_t, 0x100> visited_map;
|
||||
path.end_loc = loc;
|
||||
if (!this->check_move_path_and_get_cost(
|
||||
client_id, card_ref, &visited_map, &path, out_cost)) {
|
||||
client_id, card_ref, &visited_map, &path, out_cost)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2189,9 +2186,9 @@ bool RulerServer::is_attack_valid(const ActionState& pa) {
|
||||
(attacker_chain->chain.acting_card_ref != attacker_card_ref) ||
|
||||
!attacker_ce ||
|
||||
((attacker_ce->def.type != CardType::HUNTERS_SC &&
|
||||
(attacker_ce->def.type != CardType::ARKZ_SC) &&
|
||||
(attacker_ce->def.type != CardType::CREATURE) &&
|
||||
(attacker_ce->def.type != CardType::ITEM)))) {
|
||||
(attacker_ce->def.type != CardType::ARKZ_SC) &&
|
||||
(attacker_ce->def.type != CardType::CREATURE) &&
|
||||
(attacker_ce->def.type != CardType::ITEM)))) {
|
||||
this->error_code3 = -0x6F;
|
||||
return false;
|
||||
}
|
||||
@@ -2247,7 +2244,7 @@ bool RulerServer::is_attack_valid(const ActionState& pa) {
|
||||
}
|
||||
|
||||
if (!this->check_usability_or_apply_condition_for_card_refs(
|
||||
right_card_ref, attacker_card_ref, 0xFFFF, 0xFF, AttackMedium::INVALID_FF)) {
|
||||
right_card_ref, attacker_card_ref, 0xFFFF, 0xFF, AttackMedium::INVALID_FF)) {
|
||||
this->error_code3 = -0x6A;
|
||||
return false;
|
||||
}
|
||||
@@ -2377,7 +2374,7 @@ bool RulerServer::is_defense_valid(const ActionState& pa) {
|
||||
}
|
||||
|
||||
if (!this->defense_card_can_apply_to_attack(
|
||||
pa.action_card_refs[0], pa.target_card_refs[0], pa.original_attacker_card_ref)) {
|
||||
pa.action_card_refs[0], pa.target_card_refs[0], pa.original_attacker_card_ref)) {
|
||||
this->error_code3 = -0x61;
|
||||
return false;
|
||||
}
|
||||
@@ -2447,10 +2444,10 @@ size_t RulerServer::max_move_distance_for_card_ref(uint32_t card_ref) const {
|
||||
}
|
||||
|
||||
RulerServer::MovePath::MovePath()
|
||||
: length(-1),
|
||||
remaining_distance(0),
|
||||
num_occupied_tiles(0),
|
||||
cost(0) { }
|
||||
: length(-1),
|
||||
remaining_distance(0),
|
||||
num_occupied_tiles(0),
|
||||
cost(0) {}
|
||||
|
||||
void RulerServer::MovePath::add_step(const Location& loc) {
|
||||
this->step_locs[++this->length] = loc;
|
||||
@@ -2617,8 +2614,8 @@ const CardShortStatus* RulerServer::short_status_for_card_ref(uint16_t card_ref)
|
||||
|
||||
bool RulerServer::should_allow_attacks_on_current_turn() const {
|
||||
return (this->state_flags &&
|
||||
((this->state_flags->turn_num > 1) ||
|
||||
(this->state_flags->current_team_turn1 != this->state_flags->first_team_turn)));
|
||||
((this->state_flags->turn_num > 1) ||
|
||||
(this->state_flags->current_team_turn1 != this->state_flags->first_team_turn)));
|
||||
}
|
||||
|
||||
int32_t RulerServer::verify_deck(
|
||||
@@ -2676,6 +2673,4 @@ int32_t RulerServer::verify_deck(
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
@@ -4,15 +4,13 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "DataIndex.hh"
|
||||
#include "PlayerState.hh"
|
||||
#include "DeckState.hh"
|
||||
#include "AssistServer.hh"
|
||||
#include "DataIndex.hh"
|
||||
#include "DeckState.hh"
|
||||
#include "PlayerState.hh"
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
class Server;
|
||||
|
||||
void compute_effective_range(
|
||||
@@ -227,6 +225,4 @@ public:
|
||||
int32_t error_code3;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
+77
-91
@@ -1,7 +1,7 @@
|
||||
#include "Server.hh"
|
||||
|
||||
#include <phosg/Time.hh>
|
||||
#include <phosg/Random.hh>
|
||||
#include <phosg/Time.hh>
|
||||
|
||||
#include "../SendCommands.hh"
|
||||
|
||||
@@ -9,15 +9,11 @@ using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
// These strings in the original implementation did not contain the semicolons
|
||||
// (or anything after them).
|
||||
// This is (obviously) not the original string. The original string is:
|
||||
// "[V1][FINAL2.0] 03/09/13 15:30 by K.Toya"
|
||||
static const char* VERSION_SIGNATURE =
|
||||
"newserv Ep3 based on [V1][FINAL2.0] 03/09/13 15:30 by K.Toya";
|
||||
|
||||
|
||||
|
||||
ServerBase::PresenceEntry::PresenceEntry() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -28,19 +24,17 @@ void ServerBase::PresenceEntry::clear() {
|
||||
this->is_cpu_player = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ServerBase::ServerBase(
|
||||
shared_ptr<Lobby> lobby,
|
||||
shared_ptr<const DataIndex> data_index,
|
||||
uint32_t random_seed,
|
||||
shared_ptr<const DataIndex::MapEntry> map_if_tournament)
|
||||
: lobby(lobby),
|
||||
data_index(data_index),
|
||||
log(lobby->log.prefix + "[Ep3::Server] "),
|
||||
random_seed(random_seed),
|
||||
is_tournament(!!map_if_tournament),
|
||||
last_chosen_map(map_if_tournament) { }
|
||||
: lobby(lobby),
|
||||
data_index(data_index),
|
||||
log(lobby->log.prefix + "[Ep3::Server] "),
|
||||
random_seed(random_seed),
|
||||
is_tournament(!!map_if_tournament),
|
||||
last_chosen_map(map_if_tournament) {}
|
||||
|
||||
void ServerBase::init() {
|
||||
this->reset();
|
||||
@@ -65,46 +59,44 @@ void ServerBase::recreate_server() {
|
||||
this->server->init();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Server::Server(shared_ptr<ServerBase> base)
|
||||
: w_base(base),
|
||||
battle_finished(false),
|
||||
battle_in_progress(false),
|
||||
round_num(1),
|
||||
battle_phase(BattlePhase::INVALID_00),
|
||||
first_team_turn(0xFF),
|
||||
current_team_turn1(0xFF),
|
||||
setup_phase(SetupPhase::REGISTRATION),
|
||||
registration_phase(RegistrationPhase::AWAITING_NUM_PLAYERS),
|
||||
action_subphase(ActionSubphase::ATTACK),
|
||||
current_team_turn2(0xFF),
|
||||
num_pending_attacks(0),
|
||||
client_done_enqueuing_attacks(false),
|
||||
player_ready_to_end_phase(false),
|
||||
unknown_a10(0),
|
||||
overall_time_expired(false),
|
||||
battle_start_usecs(0),
|
||||
should_copy_prev_states_to_current_states(0),
|
||||
card_special(nullptr),
|
||||
clients_done_in_mulligan_phase(false),
|
||||
num_pending_attacks_with_cards(0),
|
||||
unknown_a14(0),
|
||||
unknown_a15(0),
|
||||
defense_list_ended_for_client(false),
|
||||
next_assist_card_set_number(1),
|
||||
team_exp(0),
|
||||
team_dice_boost(0),
|
||||
team_client_count(0),
|
||||
team_num_ally_fcs_destroyed(0),
|
||||
team_num_cards_destroyed(0),
|
||||
hard_reset_flag(false),
|
||||
tournament_flag(base->is_tournament ? 1 : 0),
|
||||
num_trap_tiles_of_type(0),
|
||||
chosen_trap_tile_index_of_type(0),
|
||||
has_done_pb(0),
|
||||
num_6xB4x06_commands_sent(0),
|
||||
prev_num_6xB4x06_commands_sent(0) { }
|
||||
: w_base(base),
|
||||
battle_finished(false),
|
||||
battle_in_progress(false),
|
||||
round_num(1),
|
||||
battle_phase(BattlePhase::INVALID_00),
|
||||
first_team_turn(0xFF),
|
||||
current_team_turn1(0xFF),
|
||||
setup_phase(SetupPhase::REGISTRATION),
|
||||
registration_phase(RegistrationPhase::AWAITING_NUM_PLAYERS),
|
||||
action_subphase(ActionSubphase::ATTACK),
|
||||
current_team_turn2(0xFF),
|
||||
num_pending_attacks(0),
|
||||
client_done_enqueuing_attacks(false),
|
||||
player_ready_to_end_phase(false),
|
||||
unknown_a10(0),
|
||||
overall_time_expired(false),
|
||||
battle_start_usecs(0),
|
||||
should_copy_prev_states_to_current_states(0),
|
||||
card_special(nullptr),
|
||||
clients_done_in_mulligan_phase(false),
|
||||
num_pending_attacks_with_cards(0),
|
||||
unknown_a14(0),
|
||||
unknown_a15(0),
|
||||
defense_list_ended_for_client(false),
|
||||
next_assist_card_set_number(1),
|
||||
team_exp(0),
|
||||
team_dice_boost(0),
|
||||
team_client_count(0),
|
||||
team_num_ally_fcs_destroyed(0),
|
||||
team_num_cards_destroyed(0),
|
||||
hard_reset_flag(false),
|
||||
tournament_flag(base->is_tournament ? 1 : 0),
|
||||
num_trap_tiles_of_type(0),
|
||||
chosen_trap_tile_index_of_type(0),
|
||||
has_done_pb(0),
|
||||
num_6xB4x06_commands_sent(0),
|
||||
prev_num_6xB4x06_commands_sent(0) {}
|
||||
|
||||
void Server::init() {
|
||||
this->card_special.reset(new CardSpecial(this->shared_from_this()));
|
||||
@@ -262,8 +254,7 @@ void Server::send_commands_for_joining_spectator(Channel& c) const {
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
void Server::log_debug(const char* fmt, ...) const {
|
||||
__attribute__((format(printf, 2, 3))) void Server::log_debug(const char* fmt, ...) const {
|
||||
auto l = this->base()->lobby.lock();
|
||||
if (l && (this->base()->data_index->behavior_flags & Episode3::BehaviorFlag::ENABLE_STATUS_MESSAGES)) {
|
||||
va_list va;
|
||||
@@ -273,8 +264,7 @@ void Server::log_debug(const char* fmt, ...) const {
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
void Server::send_debug_message_printf(const char* fmt, ...) const {
|
||||
__attribute__((format(printf, 2, 3))) void Server::send_debug_message_printf(const char* fmt, ...) const {
|
||||
auto l = this->base()->lobby.lock();
|
||||
if (l && (this->base()->data_index->behavior_flags & Episode3::BehaviorFlag::ENABLE_STATUS_MESSAGES)) {
|
||||
va_list va;
|
||||
@@ -286,8 +276,7 @@ void Server::send_debug_message_printf(const char* fmt, ...) const {
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
void Server::send_info_message_printf(const char* fmt, ...) const {
|
||||
__attribute__((format(printf, 2, 3))) void Server::send_info_message_printf(const char* fmt, ...) const {
|
||||
auto l = this->base()->lobby.lock();
|
||||
if (l) {
|
||||
va_list va;
|
||||
@@ -539,7 +528,8 @@ void Server::check_for_destroyed_cards_and_send_6xB4x05_6xB4x02() {
|
||||
|
||||
bool Server::check_presence_entry(uint8_t client_id) const {
|
||||
return (client_id < 4)
|
||||
? this->base()->presence_entries[client_id].player_present : false;
|
||||
? this->base()->presence_entries[client_id].player_present
|
||||
: false;
|
||||
}
|
||||
|
||||
void Server::clear_player_flags_after_dice_phase() {
|
||||
@@ -1220,7 +1210,6 @@ void Server::set_client_id_ready_to_advance_phase(uint8_t client_id) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Server::set_phase_after() {
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
auto ps = this->player_states[client_id];
|
||||
@@ -1513,29 +1502,29 @@ bool Server::update_registration_phase() {
|
||||
}
|
||||
|
||||
const unordered_map<uint8_t, Server::handler_t> Server::subcommand_handlers({
|
||||
{0x0B, &Server::handle_6xB3x0B_mulligan_hand},
|
||||
{0x0C, &Server::handle_6xB3x0C_end_mulligan_phase},
|
||||
{0x0D, &Server::handle_6xB3x0D_end_non_action_phase},
|
||||
{0x0E, &Server::handle_6xB3x0E_discard_card_from_hand},
|
||||
{0x0F, &Server::handle_6xB3x0F_set_card_from_hand},
|
||||
{0x10, &Server::handle_6xB3x10_move_fc_to_location},
|
||||
{0x11, &Server::handle_6xB3x11_enqueue_attack_or_defense},
|
||||
{0x12, &Server::handle_6xB3x12_end_attack_list},
|
||||
{0x13, &Server::handle_6xB3x13_update_map_during_setup},
|
||||
{0x14, &Server::handle_6xB3x14_update_deck_during_setup},
|
||||
{0x15, &Server::handle_6xB3x15_unused_hard_reset_server_state},
|
||||
{0x1B, &Server::handle_6xB3x1B_update_player_name},
|
||||
{0x1D, &Server::handle_6xB3x1D_start_battle},
|
||||
{0x21, &Server::handle_6xB3x21_end_battle},
|
||||
{0x28, &Server::handle_6xB3x28_end_defense_list},
|
||||
{0x2B, &Server::handle_6xB3x2B_ignored},
|
||||
{0x34, &Server::handle_6xB3x34_subtract_ally_atk_points},
|
||||
{0x37, &Server::handle_6xB3x37_client_ready_to_advance_from_starter_roll_phase},
|
||||
{0x3A, &Server::handle_6xB3x3A_ignored},
|
||||
{0x40, &Server::handle_6xB3x40_map_list_request},
|
||||
{0x41, &Server::handle_6xB3x41_map_request},
|
||||
{0x48, &Server::handle_6xB3x48_end_turn},
|
||||
{0x49, &Server::handle_6xB3x49_card_counts},
|
||||
{0x0B, &Server::handle_6xB3x0B_mulligan_hand},
|
||||
{0x0C, &Server::handle_6xB3x0C_end_mulligan_phase},
|
||||
{0x0D, &Server::handle_6xB3x0D_end_non_action_phase},
|
||||
{0x0E, &Server::handle_6xB3x0E_discard_card_from_hand},
|
||||
{0x0F, &Server::handle_6xB3x0F_set_card_from_hand},
|
||||
{0x10, &Server::handle_6xB3x10_move_fc_to_location},
|
||||
{0x11, &Server::handle_6xB3x11_enqueue_attack_or_defense},
|
||||
{0x12, &Server::handle_6xB3x12_end_attack_list},
|
||||
{0x13, &Server::handle_6xB3x13_update_map_during_setup},
|
||||
{0x14, &Server::handle_6xB3x14_update_deck_during_setup},
|
||||
{0x15, &Server::handle_6xB3x15_unused_hard_reset_server_state},
|
||||
{0x1B, &Server::handle_6xB3x1B_update_player_name},
|
||||
{0x1D, &Server::handle_6xB3x1D_start_battle},
|
||||
{0x21, &Server::handle_6xB3x21_end_battle},
|
||||
{0x28, &Server::handle_6xB3x28_end_defense_list},
|
||||
{0x2B, &Server::handle_6xB3x2B_ignored},
|
||||
{0x34, &Server::handle_6xB3x34_subtract_ally_atk_points},
|
||||
{0x37, &Server::handle_6xB3x37_client_ready_to_advance_from_starter_roll_phase},
|
||||
{0x3A, &Server::handle_6xB3x3A_ignored},
|
||||
{0x40, &Server::handle_6xB3x40_map_list_request},
|
||||
{0x41, &Server::handle_6xB3x41_map_request},
|
||||
{0x48, &Server::handle_6xB3x48_end_turn},
|
||||
{0x49, &Server::handle_6xB3x49_card_counts},
|
||||
});
|
||||
|
||||
void Server::on_server_data_input(const string& data) {
|
||||
@@ -2025,7 +2014,7 @@ void Server::handle_6xB3x28_end_defense_list(const string& data) {
|
||||
this->send(out_cmd_fin);
|
||||
}
|
||||
|
||||
void Server::handle_6xB3x2B_ignored(const string&) { }
|
||||
void Server::handle_6xB3x2B_ignored(const string&) {}
|
||||
|
||||
void Server::handle_6xB3x34_subtract_ally_atk_points(const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_PhotonBlastRequest_GC_Ep3_6xB3x34_CAx34>(data);
|
||||
@@ -2131,7 +2120,7 @@ void Server::handle_6xB3x37_client_ready_to_advance_from_starter_roll_phase(cons
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handle_6xB3x3A_ignored(const string&) { }
|
||||
void Server::handle_6xB3x3A_ignored(const string&) {}
|
||||
|
||||
void Server::handle_6xB3x40_map_list_request(const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_MapListRequest_GC_Ep3_6xB3x40_CAx40>(data);
|
||||
@@ -2379,7 +2368,7 @@ void Server::unknown_8023EEF4() {
|
||||
if (!this->attack_cards[this->unknown_a14]->action_chain.check_flag(0x40)) {
|
||||
this->card_special->unknown_8024945C(this->attack_cards[this->unknown_a14], as);
|
||||
}
|
||||
this->attack_cards[this->unknown_a14]->compute_action_chain_results(1,0);
|
||||
this->attack_cards[this->unknown_a14]->compute_action_chain_results(1, 0);
|
||||
this->attack_cards[this->unknown_a14]->unknown_80236374(this->attack_cards[this->unknown_a14], &as);
|
||||
if (!this->attack_cards[this->unknown_a14]->action_chain.check_flag(0x40)) {
|
||||
this->card_special->unknown_8024966C(this->attack_cards[this->unknown_a14], &as);
|
||||
@@ -2653,7 +2642,6 @@ void Server::send_6xB4x05() {
|
||||
this->send(cmd);
|
||||
}
|
||||
|
||||
|
||||
void Server::send_6xB4x02_for_all_players_if_needed(bool always_send) {
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto ps = this->player_states[z];
|
||||
@@ -2680,6 +2668,4 @@ void Server::send_6xB4x50_trap_tile_locations() const {
|
||||
this->send(this->prepare_6xB4x50_trap_tile_locations());
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
+7
-15
@@ -4,9 +4,9 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "../Text.hh"
|
||||
#include "../CommandFormats.hh"
|
||||
#include "../Channel.hh"
|
||||
#include "../CommandFormats.hh"
|
||||
#include "../Text.hh"
|
||||
#include "AssistServer.hh"
|
||||
#include "CardSpecial.hh"
|
||||
#include "MapState.hh"
|
||||
@@ -17,8 +17,6 @@ struct Lobby;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This implementation of Episode 3 battles (contained in all files in the
|
||||
* src/Episode3 directory, except for DataIndex.hh/cc) is derived from Sega's
|
||||
@@ -27,7 +25,7 @@ namespace Episode3 {
|
||||
* in these files map very closely to how their server implementation was
|
||||
* written; notable differences (due to necessary environment differences or bug
|
||||
* fixes) are described in the comments therein.
|
||||
*
|
||||
*
|
||||
* Some debugging functions have been added which are not part of the original
|
||||
* implementation. Notably, this applies to functions like debug message senders
|
||||
* and loggers and all str() functions.
|
||||
@@ -55,8 +53,6 @@ namespace Episode3 {
|
||||
|
||||
class Server;
|
||||
|
||||
|
||||
|
||||
class ServerBase : public std::enable_shared_from_this<ServerBase> {
|
||||
public:
|
||||
ServerBase(
|
||||
@@ -122,13 +118,10 @@ public:
|
||||
|
||||
void send_commands_for_joining_spectator(Channel& ch) const;
|
||||
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
void log_debug(const char* fmt, ...) const;
|
||||
__attribute__((format(printf, 2, 3))) void log_debug(const char* fmt, ...) const;
|
||||
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
void send_debug_message_printf(const char* fmt, ...) const;
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
void send_info_message_printf(const char* fmt, ...) const;
|
||||
__attribute__((format(printf, 2, 3))) void send_debug_message_printf(const char* fmt, ...) const;
|
||||
__attribute__((format(printf, 2, 3))) void send_info_message_printf(const char* fmt, ...) const;
|
||||
void send_debug_command_received_message(
|
||||
uint8_t client_id, uint8_t subsubcommand, const char* description) const;
|
||||
void send_debug_command_received_message(
|
||||
@@ -241,6 +234,7 @@ public:
|
||||
|
||||
std::vector<std::shared_ptr<Card>> const_cast_set_cards_v(
|
||||
const std::vector<std::shared_ptr<const Card>>& cards);
|
||||
|
||||
private:
|
||||
typedef void (Server::*handler_t)(const std::string&);
|
||||
static const std::unordered_map<uint8_t, handler_t> subcommand_handlers;
|
||||
@@ -301,6 +295,4 @@ public:
|
||||
mutable uint32_t prev_num_6xB4x06_commands_sent;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
+44
-55
@@ -9,14 +9,14 @@ using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
|
||||
|
||||
Tournament::PlayerEntry::PlayerEntry(uint32_t serial_number)
|
||||
: serial_number(serial_number), com_deck() { }
|
||||
: serial_number(serial_number),
|
||||
com_deck() {}
|
||||
|
||||
Tournament::PlayerEntry::PlayerEntry(
|
||||
shared_ptr<const COMDeckDefinition> com_deck)
|
||||
: serial_number(0), com_deck(com_deck) { }
|
||||
: serial_number(0),
|
||||
com_deck(com_deck) {}
|
||||
|
||||
bool Tournament::PlayerEntry::is_com() const {
|
||||
return (this->com_deck != nullptr);
|
||||
@@ -26,17 +26,15 @@ bool Tournament::PlayerEntry::is_human() const {
|
||||
return (this->serial_number != 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Tournament::Team::Team(
|
||||
shared_ptr<Tournament> tournament, size_t index, size_t max_players)
|
||||
: tournament(tournament),
|
||||
index(index),
|
||||
max_players(max_players),
|
||||
name(""),
|
||||
password(""),
|
||||
num_rounds_cleared(0),
|
||||
is_active(true) { }
|
||||
: tournament(tournament),
|
||||
index(index),
|
||||
max_players(max_players),
|
||||
name(""),
|
||||
password(""),
|
||||
num_rounds_cleared(0),
|
||||
is_active(true) {}
|
||||
|
||||
string Tournament::Team::str() const {
|
||||
size_t num_human_players = 0;
|
||||
@@ -133,8 +131,8 @@ bool Tournament::Team::unregister_player(uint32_t serial_number) {
|
||||
}
|
||||
}
|
||||
|
||||
// If the tournament has not started yet, just remove the player from the
|
||||
// team
|
||||
// If the tournament has not started yet, just remove the player from the
|
||||
// team
|
||||
} else {
|
||||
if (!tournament->all_player_serial_numbers.erase(serial_number)) {
|
||||
throw logic_error("player removed from team but not from tournament");
|
||||
@@ -173,17 +171,15 @@ size_t Tournament::Team::num_com_players() const {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Tournament::Match::Match(
|
||||
shared_ptr<Tournament> tournament,
|
||||
shared_ptr<Match> preceding_a,
|
||||
shared_ptr<Match> preceding_b)
|
||||
: tournament(tournament),
|
||||
preceding_a(preceding_a),
|
||||
preceding_b(preceding_b),
|
||||
winner_team(nullptr),
|
||||
round_num(0) {
|
||||
: tournament(tournament),
|
||||
preceding_a(preceding_a),
|
||||
preceding_b(preceding_b),
|
||||
winner_team(nullptr),
|
||||
round_num(0) {
|
||||
if (this->preceding_a->round_num != this->preceding_b->round_num) {
|
||||
throw logic_error("preceding matches have different round numbers");
|
||||
}
|
||||
@@ -193,11 +189,11 @@ Tournament::Match::Match(
|
||||
Tournament::Match::Match(
|
||||
shared_ptr<Tournament> tournament,
|
||||
shared_ptr<Team> winner_team)
|
||||
: tournament(tournament),
|
||||
preceding_a(nullptr),
|
||||
preceding_b(nullptr),
|
||||
winner_team(winner_team),
|
||||
round_num(0) { }
|
||||
: tournament(tournament),
|
||||
preceding_a(nullptr),
|
||||
preceding_b(nullptr),
|
||||
winner_team(winner_team),
|
||||
round_num(0) {}
|
||||
|
||||
string Tournament::Match::str() const {
|
||||
string winner_str = this->winner_team ? this->winner_team->str() : "(none)";
|
||||
@@ -216,7 +212,8 @@ bool Tournament::Match::resolve_if_no_human_players() {
|
||||
!this->preceding_a->winner_team->has_any_human_players() &&
|
||||
!this->preceding_b->winner_team->has_any_human_players()) {
|
||||
this->set_winner_team((random_object<uint8_t>() & 1)
|
||||
? this->preceding_b->winner_team : this->preceding_a->winner_team);
|
||||
? this->preceding_b->winner_team
|
||||
: this->preceding_a->winner_team);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -282,8 +279,6 @@ shared_ptr<Tournament::Team> Tournament::Match::opponent_team_for_team(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Tournament::Tournament(
|
||||
shared_ptr<const DataIndex> data_index,
|
||||
uint8_t number,
|
||||
@@ -292,15 +287,15 @@ Tournament::Tournament(
|
||||
const Rules& rules,
|
||||
size_t num_teams,
|
||||
bool is_2v2)
|
||||
: log(string_printf("[Tournament/%02hhX] ", number)),
|
||||
data_index(data_index),
|
||||
number(number),
|
||||
name(name),
|
||||
map(map),
|
||||
rules(rules),
|
||||
num_teams(num_teams),
|
||||
is_2v2(is_2v2),
|
||||
current_state(State::REGISTRATION) {
|
||||
: log(string_printf("[Tournament/%02hhX] ", number)),
|
||||
data_index(data_index),
|
||||
number(number),
|
||||
name(name),
|
||||
map(map),
|
||||
rules(rules),
|
||||
num_teams(num_teams),
|
||||
is_2v2(is_2v2),
|
||||
current_state(State::REGISTRATION) {
|
||||
if (this->num_teams < 4) {
|
||||
throw invalid_argument("team count must be 4 or more");
|
||||
}
|
||||
@@ -316,11 +311,11 @@ Tournament::Tournament(
|
||||
std::shared_ptr<const DataIndex> data_index,
|
||||
uint8_t number,
|
||||
std::shared_ptr<const JSONObject> json)
|
||||
: log(string_printf("[Tournament/%02hhX] ", number)),
|
||||
data_index(data_index),
|
||||
source_json(json),
|
||||
number(number),
|
||||
current_state(State::REGISTRATION) { }
|
||||
: log(string_printf("[Tournament/%02hhX] ", number)),
|
||||
data_index(data_index),
|
||||
source_json(json),
|
||||
number(number),
|
||||
current_state(State::REGISTRATION) {}
|
||||
|
||||
void Tournament::init() {
|
||||
vector<size_t> team_index_to_rounds_cleared;
|
||||
@@ -414,10 +409,8 @@ void Tournament::init() {
|
||||
if (!match->preceding_a->winner_team || !match->preceding_b->winner_team) {
|
||||
throw logic_error("preceding matches are not resolved");
|
||||
}
|
||||
size_t& a_rounds_cleared = team_index_to_rounds_cleared[
|
||||
match->preceding_a->winner_team->index];
|
||||
size_t& b_rounds_cleared = team_index_to_rounds_cleared[
|
||||
match->preceding_b->winner_team->index];
|
||||
size_t& a_rounds_cleared = team_index_to_rounds_cleared[match->preceding_a->winner_team->index];
|
||||
size_t& b_rounds_cleared = team_index_to_rounds_cleared[match->preceding_b->winner_team->index];
|
||||
if (a_rounds_cleared && b_rounds_cleared) {
|
||||
throw runtime_error("both teams won the same match");
|
||||
}
|
||||
@@ -469,8 +462,7 @@ std::shared_ptr<JSONObject> Tournament::json() const {
|
||||
dict.emplace("map_number", make_json_int(this->map->map.map_number));
|
||||
dict.emplace("rules", this->rules.json());
|
||||
dict.emplace("is_2v2", make_json_bool(this->is_2v2));
|
||||
dict.emplace("is_registration_complete", make_json_bool(
|
||||
this->current_state != State::REGISTRATION));
|
||||
dict.emplace("is_registration_complete", make_json_bool(this->current_state != State::REGISTRATION));
|
||||
|
||||
vector<shared_ptr<JSONObject>> teams_list;
|
||||
for (auto team : this->teams) {
|
||||
@@ -661,13 +653,12 @@ void Tournament::print_bracket(FILE* stream) const {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
TournamentIndex::TournamentIndex(
|
||||
shared_ptr<const DataIndex> data_index,
|
||||
const string& state_filename,
|
||||
bool skip_load_state)
|
||||
: data_index(data_index), state_filename(state_filename) {
|
||||
: data_index(data_index),
|
||||
state_filename(state_filename) {
|
||||
if (this->state_filename.empty() || skip_load_state) {
|
||||
return;
|
||||
}
|
||||
@@ -768,6 +759,4 @@ shared_ptr<Tournament::Team> TournamentIndex::team_for_serial_number(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <event2/event.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
#include <phosg/JSON.hh>
|
||||
#include <phosg/Strings.hh>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "../Player.hh"
|
||||
|
||||
@@ -18,8 +18,6 @@ namespace Episode3 {
|
||||
|
||||
// The comment in Server.hh does not apply to this file (and Tournament.cc).
|
||||
|
||||
|
||||
|
||||
class Tournament : public std::enable_shared_from_this<Tournament> {
|
||||
public:
|
||||
enum class State {
|
||||
@@ -172,11 +170,11 @@ public:
|
||||
std::vector<std::shared_ptr<Tournament>> all_tournaments() const;
|
||||
|
||||
std::shared_ptr<Tournament> create_tournament(
|
||||
const std::string& name,
|
||||
std::shared_ptr<const DataIndex::MapEntry> map,
|
||||
const Rules& rules,
|
||||
size_t num_teams,
|
||||
bool is_2v2);
|
||||
const std::string& name,
|
||||
std::shared_ptr<const DataIndex::MapEntry> map,
|
||||
const Rules& rules,
|
||||
size_t num_teams,
|
||||
bool is_2v2);
|
||||
void delete_tournament(uint8_t number);
|
||||
std::shared_ptr<Tournament> get_tournament(uint8_t number) const;
|
||||
std::shared_ptr<Tournament> get_tournament(const std::string& name) const;
|
||||
@@ -190,6 +188,4 @@ private:
|
||||
std::shared_ptr<Tournament> tournaments[0x20];
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
Reference in New Issue
Block a user