diff --git a/_common/include/Packet.hpp b/_common/include/Packet.hpp index 5fd11b7..77f8745 100644 --- a/_common/include/Packet.hpp +++ b/_common/include/Packet.hpp @@ -25,6 +25,7 @@ enum class PacketType { CLIENT_READY, END_GAME, NEXT_PHASE, + COMBO_INDEX, }; class Packet { private: diff --git a/_common/include/Player.hpp b/_common/include/Player.hpp index dd5b41d..04f25e2 100644 --- a/_common/include/Player.hpp +++ b/_common/include/Player.hpp @@ -13,12 +13,7 @@ #include "NetTransform.hpp" #include "Mover.hpp" -enum Keys { - I = 73, - J = 74, - K = 75, - L = 76 -}; +enum Keys { I = 73, J = 74, K = 75, L = 76 }; class Player : public Entity { public: @@ -26,6 +21,7 @@ class Player : public Entity { // glm::vec3 velocity = glm::vec3(); // float speed = 0.2f; bool alive; + int clientId = -1; // I = 73, J = 74, K = 75, L = 76 std::vector attack1 = {J, J, J, J}; @@ -37,7 +33,7 @@ class Player : public Entity { int32_t TypeID() const override { return PLAYER; } // Used by server - Player(glm::vec3 position); + Player(glm::vec3 position, int clientId); void onDestroy(); virtual void update(float deltaTime) override; diff --git a/client/src/GameManager.cpp b/client/src/GameManager.cpp index 5753baa..4455424 100644 --- a/client/src/GameManager.cpp +++ b/client/src/GameManager.cpp @@ -63,6 +63,11 @@ void GameManager::handle_packet(Packet* packet) { std::cout << "GAME OVER" << std::endl; } break; + case PacketType::COMBO_INDEX: + int index; + packet->read_int(&index); + printf("combo index: %d\n", index); + break; default: std::cout << " PacketType: ERROR" << std::endl; break; @@ -82,10 +87,11 @@ void GameManager::update(Packet* pkt) { case NetworkObjectTypeID::ENEMY: { // std::cout << " ObjTypeID: Enemy" << std::endl; int network_id; - pkt->read_int(&network_id); // J: I did not thoroughly check if the packet is read correctly + pkt->read_int(&network_id); // J: I did not thoroughly check if the + // packet is read correctly if (!boss) { boss = new Enemy(enemyPath, network_id); - std::vector prefabClips = + std::vector prefabClips = AssetManager::Instance().GetClips(enemyPath); for (int i = 0; i < prefabClips.size(); i++) { AnimationClip* clip = new AnimationClip(prefabClips[i]); @@ -97,8 +103,10 @@ void GameManager::update(Packet* pkt) { boss->deserialize(pkt); - // also look up at the boss, probably needs to be the center of it which is like 1000 or something rn - glm::vec3 bossPos = boss->GetComponent()->GetPosition(); + // also look up at the boss, probably needs to be the center of it + // which is like 1000 or something rn + glm::vec3 bossPos = + boss->GetComponent()->GetPosition(); cam->SetTarget(glm::vec3(bossPos.x, 0.0f, bossPos.z)); break; @@ -116,7 +124,8 @@ void GameManager::update(Packet* pkt) { AnimationClip* clip = new AnimationClip(prefabClips[i]); // std::cout << "Adding clip: " << clip->getName() // << std::endl; - playerPrefab->GetComponent()->AddClip(clip); + playerPrefab->GetComponent()->AddClip( + clip); } players[network_id] = playerPrefab; @@ -159,7 +168,7 @@ void GameManager::update(Packet* pkt) { players[network_id]->deserialize(pkt); if (localPlayerObject == network_id) { - + auto playerPos = players[localPlayerObject] ->GetComponent() ->position; @@ -172,7 +181,9 @@ void GameManager::update(Packet* pkt) { glm::vec3(0, 2.0f, 0) + playerRightVector * 0.7f); } - // std::cout << players[network_id]->GetComponent()->ToString() << std::endl; + // std::cout << + // players[network_id]->GetComponent()->ToString() << + // std::endl; break; } @@ -184,14 +195,15 @@ void GameManager::update(Packet* pkt) { if (playerSkills.find(network_id) == playerSkills.end()) { PlayerSkill* playerSkillPrefab = new PlayerSkill(network_id); playerSkillPrefab->deserialize(pkt); - playerSkillPrefab->initComponent(playerSkillPrefab->GetComponent()->GetState()); + playerSkillPrefab->initComponent( + playerSkillPrefab->GetComponent() + ->GetState()); playerSkills[network_id] = playerSkillPrefab; scene.Instantiate(playerSkillPrefab); - } - else { + } else { playerSkills[network_id]->deserialize(pkt); } - + break; } case NetworkObjectTypeID::ENEMY_ATTACK: { @@ -200,7 +212,9 @@ void GameManager::update(Packet* pkt) { pkt->read_int(&network_id); // Could not find object, create it if (enemyAttacks.find(network_id) == enemyAttacks.end()) { - EnemyAttack* enemyAttackPrefab = new EnemyAttack(boss->GetComponent()->GetState(), network_id); + EnemyAttack* enemyAttackPrefab = new EnemyAttack( + boss->GetComponent()->GetState(), + network_id); enemyAttacks[network_id] = enemyAttackPrefab; scene.Instantiate(enemyAttackPrefab); diff --git a/server/components/PlayerCombat.cpp b/server/components/PlayerCombat.cpp index f1b9228..001e809 100644 --- a/server/components/PlayerCombat.cpp +++ b/server/components/PlayerCombat.cpp @@ -1,5 +1,18 @@ #include "PlayerCombat.hpp" #include "Health.hpp" +#include +#include + +void PlayerCombat::Update(float deltaTime) { + timeSinceLastInput += deltaTime; + + if (timeSinceLastInput >= COMBO_RESET_TIME && shouldResetCombo) { + ResetAllCombos(); + shouldResetCombo = false; + + NetworkManager::instance().send_combo(((Player*)owner)->clientId, 0); + } +} void PlayerCombat::AddCombo(const std::vector& sequence) { Combo combo; @@ -12,6 +25,11 @@ std::vector PlayerCombat::CheckCombo(int input) { if (owner->GetComponent()->GetDead()) { return {}; } + + timeSinceLastInput = 0; + shouldResetCombo = true; + + int maxComboIndex = 0; for (auto& combo : combos) { // Check if current input matches combo's input if (combo.sequence[combo.comboIndex] != input) { @@ -22,13 +40,22 @@ std::vector PlayerCombat::CheckCombo(int input) { combo.comboIndex++; + if (combo.comboIndex > maxComboIndex) { + maxComboIndex = combo.comboIndex; + } + // Reached end of combo, success if (combo.comboIndex == combo.sequence.size()) { ResetAllCombos(); + NetworkManager::instance().send_combo(((Player*)owner)->clientId, + maxComboIndex); return combo.sequence; } } + NetworkManager::instance().send_combo(((Player*)owner)->clientId, + maxComboIndex); + return {}; } diff --git a/server/components/PlayerCombat.hpp b/server/components/PlayerCombat.hpp index e865c08..6a6681c 100644 --- a/server/components/PlayerCombat.hpp +++ b/server/components/PlayerCombat.hpp @@ -2,8 +2,12 @@ #include #include "IComponent.hpp" +#define COMBO_RESET_TIME 0.5172 * 4 + class PlayerCombat : public IComponent { private: + float timeSinceLastInput = 0; + bool shouldResetCombo = true; struct Combo { int comboIndex; std::vector sequence; @@ -16,6 +20,7 @@ class PlayerCombat : public IComponent { std::vector CheckCombo(int input); void ResetCombo(Combo& combo); void ResetAllCombos(); + void Update(float deltaTime) override; std::string ToString() { return "PlayerCombat"; } }; \ No newline at end of file diff --git a/server/include/NetworkManager.hpp b/server/include/NetworkManager.hpp index ec2e070..e30a06c 100644 --- a/server/include/NetworkManager.hpp +++ b/server/include/NetworkManager.hpp @@ -21,6 +21,7 @@ class NetworkManager { void send_state(); void process_input(); void send_next_phase(); + void send_combo(int clientId, int comboIndex); void on_message_received(const EventArgs* e); void on_client_joined(const EventArgs* e); static NetworkManager& instance() { diff --git a/server/src/NetworkManager.cpp b/server/src/NetworkManager.cpp index 01ec232..bd146d1 100644 --- a/server/src/NetworkManager.cpp +++ b/server/src/NetworkManager.cpp @@ -27,9 +27,9 @@ Server server; bool isServerReady = false; int playersReady = 0; Enemy* enemyPrefab; -std::vector spawnPoints = { - glm::vec3(60, 0, 0), glm::vec3(0, 0, 60), glm::vec3(-60, 0, 0), - glm::vec3(0, 0, -60)}; +std::vector spawnPoints = {glm::vec3(60, 0, 0), glm::vec3(0, 0, 60), + glm::vec3(-60, 0, 0), + glm::vec3(0, 0, -60)}; int spawnIndex = 0; union FloatUnion { float f; @@ -162,14 +162,17 @@ void NetworkManager::process_input() { ->p->GetComponent() ->ResetAllCombos(); printf(RED "MISSED\n" RST); + send_combo(client_id, 0); break; } - std::vector comboSeq = clients[client_id]->p->GetComponent()->CheckCombo(key); + std::vector comboSeq = + clients[client_id]->p->GetComponent()->CheckCombo( + key); if (!comboSeq.empty()) { printf(YLW "COMBO HIT\n" RST); - - if (comboSeq == clients[client_id]->p->attack1 || + + if (comboSeq == clients[client_id]->p->attack1 || comboSeq == clients[client_id]->p->attack2) { AttackManager::instance().newPlayerAttack( clients[client_id]->p); @@ -226,7 +229,8 @@ void NetworkManager::process_input() { void NetworkManager::update(float deltaTime) { // AttackManager update goes first so that whatever needs to be destroyed - // gets destroyed in the next tick, to account for effects that happen instantaneously + // gets destroyed in the next tick, to account for effects that happen + // instantaneously AttackManager::instance().update(deltaTime); scene.Update(deltaTime); } @@ -298,6 +302,13 @@ void NetworkManager::send_next_phase() { } } +void NetworkManager::send_combo(int clientId, int comboIndex) { + Packet* p = new Packet(); + p->write_int((int)PacketType::COMBO_INDEX); + p->write_int(comboIndex); + server.send(clientId, p); +} + // FIXME handle incomplete packets or multiple packets per send() call // thread-safe void NetworkManager::on_message_received(const EventArgs* e) { @@ -316,7 +327,7 @@ void NetworkManager::on_client_joined(const EventArgs* e) { // Give client control over player glm::vec3 position = spawnPoints[spawnIndex++ % spawnPoints.size()]; - Player* p = new Player(position); + Player* p = new Player(position, args->clientId); server.clients[args->clientId]->p = p; AttackManager::instance().addPlayer(p); numAlive++; diff --git a/server/src/Player.cpp b/server/src/Player.cpp index 83a706f..7823239 100644 --- a/server/src/Player.cpp +++ b/server/src/Player.cpp @@ -10,7 +10,8 @@ #include "CooldownComponent.hpp" #include "MovementStateMachine.hpp" -Player::Player(glm::vec3 position) : Entity() { +Player::Player(glm::vec3 position, int clientId) : Entity() { + this->clientId = clientId; this->GetComponent()->SetPosition(position); alive = true; Mover* mover = new Mover(this);