diff --git a/MakefileNSO b/MakefileNSO index 1d2bc7f..6273fd6 100644 --- a/MakefileNSO +++ b/MakefileNSO @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- TARGET ?= $(notdir $(CURDIR))$(SMOVER) BUILD ?= build$(SMOVER) -SOURCES := source/sead/time source/sead source/puppets source/server/hns source/server/gamemode source/server/gamemode/modifiers source/server source/layouts source/states source/cameras source/nx source +SOURCES := source/sead/time source/sead source/puppets source/server/hns source/server/snh source/server/gamemode source/server/gamemode/modifiers source/server source/layouts source/states source/cameras source/nx source SOURCES += source/al/execute DATA := data INCLUDES := include include/sead diff --git a/include/SocketBase.hpp b/include/SocketBase.hpp index 02feca5..14f119e 100644 --- a/include/SocketBase.hpp +++ b/include/SocketBase.hpp @@ -13,6 +13,8 @@ class SocketBase { virtual nn::Result init(const char * ip, u16 port) = 0; virtual bool closeSocket(); + virtual bool tryReconnect(); + virtual struct Packet *tryGetPacket(); const char *getStateChar(); u8 getLogState(); @@ -37,6 +39,3 @@ class SocketBase { int sock_flags; }; - - - diff --git a/include/layouts/SardineIcon.h b/include/layouts/SardineIcon.h new file mode 100644 index 0000000..22bb8ca --- /dev/null +++ b/include/layouts/SardineIcon.h @@ -0,0 +1,36 @@ +#pragma once + +#include "al/layout/LayoutActor.h" +#include "al/layout/LayoutInitInfo.h" +#include "al/util/NerveUtil.h" + +#include "logger.hpp" +#include "server/gamemode/GameModeTimer.hpp" + +// TODO: kill layout if going through loading zone or paused + +class SardineIcon : public al::LayoutActor { +public: + SardineIcon(const char* name, const al::LayoutInitInfo& initInfo); + + void appear() override; + + bool tryStart(); + bool tryEnd(); + + void showSolo(); + void showPack(); + + void exeAppear(); + void exeWait(); + void exeEnd(); + +private: + struct SardineInfo* mInfo; +}; + +namespace { +NERVE_HEADER(SardineIcon, Appear) +NERVE_HEADER(SardineIcon, Wait) +NERVE_HEADER(SardineIcon, End) +} \ No newline at end of file diff --git a/include/server/SocketClient.hpp b/include/server/SocketClient.hpp index 2f6dd74..5fb1770 100644 --- a/include/server/SocketClient.hpp +++ b/include/server/SocketClient.hpp @@ -24,8 +24,9 @@ class SocketClient : public SocketBase { public: SocketClient(const char *name, sead::Heap *heap); nn::Result init(const char* ip, u16 port) override; - bool tryReconnect(); + bool tryReconnect() override; bool closeSocket() override; + Packet *tryGetPacket() override; bool startThreads(); void endThreads(); @@ -39,8 +40,6 @@ class SocketClient : public SocketBase { void sendFunc(); void recvFunc(); - Packet *tryGetPacket(sead::MessageQueue::BlockType blockType = sead::MessageQueue::BlockType::Blocking); - void printPacket(Packet* packet); bool isConnected() { return socket_log_state == SOCKET_LOG_CONNECTED; } diff --git a/include/server/gamemode/GameModeBase.hpp b/include/server/gamemode/GameModeBase.hpp index e7e4715..e8a3e3f 100644 --- a/include/server/gamemode/GameModeBase.hpp +++ b/include/server/gamemode/GameModeBase.hpp @@ -1,8 +1,5 @@ #pragma once -#include -#include -#include "puppets/PuppetHolder.hpp" #include "al/actor/ActorInitInfo.h" #include "al/actor/IUseName.h" #include "al/scene/Scene.h" @@ -11,35 +8,41 @@ #include "game/StageScene/StageScene.h" #include "layouts/HideAndSeekIcon.h" #include "prim/seadSafeString.h" +#include "puppets/PuppetHolder.hpp" #include "server/gamemode/GameModeConfigMenu.hpp" +#include +#include + // enum for defining game mode types enum GameMode : s8 { NONE = -1, - HIDEANDSEEK + HIDEANDSEEK, + SARDINE }; // struct containing info about the games state for use in gamemodes struct GameModeInitInfo { - GameModeInitInfo(al::ActorInitInfo* info, al::Scene *scene){ + GameModeInitInfo(al::ActorInitInfo* info, al::Scene* scene) + { mLayoutInitInfo = info->mLayoutInitInfo; mPlayerHolder = info->mActorSceneInfo.mPlayerHolder; mSceneObjHolder = info->mActorSceneInfo.mSceneObjHolder; mScene = scene; - }; - void initServerInfo(GameMode mode, PuppetHolder *pupHolder) { + void initServerInfo(GameMode mode, PuppetHolder* pupHolder) + { mMode = mode; mPuppetHolder = pupHolder; } - + al::LayoutInitInfo* mLayoutInitInfo; al::PlayerHolder* mPlayerHolder; - al::SceneObjHolder *mSceneObjHolder; + al::SceneObjHolder* mSceneObjHolder; al::Scene* mScene; GameMode mMode = GameMode::NONE; - PuppetHolder *mPuppetHolder; + PuppetHolder* mPuppetHolder; }; // base class for all gamemodes, must inherit from this to have a functional gamemode @@ -54,18 +57,18 @@ public: virtual bool isModeActive() const { return mIsActive; } - virtual void init(GameModeInitInfo const &info); + virtual void init(GameModeInitInfo const& info); virtual void begin() { mIsActive = true; } virtual void update(); virtual void end() { mIsActive = false; } - + protected: sead::FixedSafeString<0x10> mName; - al::SceneObjHolder *mSceneObjHolder = nullptr; + al::SceneObjHolder* mSceneObjHolder = nullptr; GameMode mMode = GameMode::NONE; StageScene* mCurScene = nullptr; - PuppetHolder *mPuppetHolder = nullptr; + PuppetHolder* mPuppetHolder = nullptr; bool mIsActive = false; bool mIsFirstFrame = true; }; \ No newline at end of file diff --git a/include/server/gamemode/GameModeConfigMenuFactory.hpp b/include/server/gamemode/GameModeConfigMenuFactory.hpp index d76d307..db89180 100644 --- a/include/server/gamemode/GameModeConfigMenuFactory.hpp +++ b/include/server/gamemode/GameModeConfigMenuFactory.hpp @@ -2,6 +2,7 @@ #include "al/factory/Factory.h" #include "server/hns/HideAndSeekConfigMenu.hpp" +#include "server/snh/SardineConfigMenu.hpp" #include "server/gamemode/GameModeConfigMenu.hpp" typedef GameModeConfigMenu* (*createMenu)(const char* name); @@ -13,6 +14,7 @@ GameModeConfigMenu* createGameModeConfigMenu(const char* name) { __attribute((used)) constexpr al::NameToCreator menuTable[] = { {"HideAndSeek", &createGameModeConfigMenu}, + {"Sardine", &createGameModeConfigMenu}, }; class GameModeConfigMenuFactory : public al::Factory { diff --git a/include/server/gamemode/GameModeFactory.hpp b/include/server/gamemode/GameModeFactory.hpp index 27ca263..73158a0 100644 --- a/include/server/gamemode/GameModeFactory.hpp +++ b/include/server/gamemode/GameModeFactory.hpp @@ -3,6 +3,7 @@ #include "al/factory/Factory.h" #include "server/gamemode/GameModeBase.hpp" #include "server/hns/HideAndSeekMode.hpp" +#include "server/snh/SardineMode.hpp" typedef GameModeBase* (*createMode)(const char* name); @@ -13,11 +14,13 @@ GameModeBase* createGameMode(const char* name) }; __attribute((used)) constexpr al::NameToCreator modeTable[] = { - {"HideAndSeek", &createGameMode} + {"HideAndSeek", &createGameMode}, + {"Sardines", &createGameMode} }; constexpr const char* modeNames[] = { - "Hide and Seek" + "Hide and Seek", + "Sardines" }; class GameModeFactory : public al::Factory { diff --git a/include/server/snh/SardineConfigMenu.hpp b/include/server/snh/SardineConfigMenu.hpp new file mode 100644 index 0000000..226bc9b --- /dev/null +++ b/include/server/snh/SardineConfigMenu.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "server/gamemode/GameModeConfigMenu.hpp" +#include "game/Layouts/CommonVerticalList.h" +#include "server/gamemode/GameModeBase.hpp" + +class SardineConfigMenu : public GameModeConfigMenu { +public: + SardineConfigMenu(); + + void initMenu(const al::LayoutInitInfo &initInfo) override; + const sead::WFixedSafeString<0x200> *getStringData() override; + bool updateMenu(int selectIndex) override; + + const int getMenuSize() override { return mItemCount; } + +private: + static constexpr int mItemCount = 4; +}; \ No newline at end of file diff --git a/include/server/snh/SardineMode.hpp b/include/server/snh/SardineMode.hpp new file mode 100644 index 0000000..de04edb --- /dev/null +++ b/include/server/snh/SardineMode.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include "al/camera/CameraTicket.h" +#include "server/gamemode/GameModeBase.hpp" +#include "server/gamemode/GameModeConfigMenu.hpp" +#include "server/gamemode/GameModeInfoBase.hpp" +#include "server/gamemode/GameModeTimer.hpp" +#include "server/snh/SardineConfigMenu.hpp" +#include "layouts/SardineIcon.h" +#include + +struct SardineInfo : GameModeInfoBase { + SardineInfo() { mMode = GameMode::SARDINE; } + bool mIsIt = false; + bool mIsUseGravity = false; + bool mIsUseGravityCam = false; + bool mIsTether = true; + + GameTime mHidingTime; +}; + +class SardineMode : public GameModeBase { +public: + SardineMode(const char* name); + + void init(GameModeInitInfo const& info) override; + + virtual void begin() override; + virtual void update() override; + virtual void end() override; + + bool isPlayerIt() const { return mInfo->mIsIt; }; + + void setPlayerTagState(bool state) { mInfo->mIsIt = state; } + + void enableGravityMode() { mInfo->mIsUseGravity = true; } + void disableGravityMode() { mInfo->mIsUseGravity = false; } + bool isUseGravity() const { return mInfo->mIsUseGravity; } + + void setCameraTicket(al::CameraTicket* ticket) { mTicket = ticket; } + +private: + GameModeTimer* mModeTimer = nullptr; + SardineIcon* mModeLayout = nullptr; + SardineInfo* mInfo = nullptr; + al::CameraTicket* mTicket = nullptr; + + float pullDistanceMax = 2250.f; + float pullDistanceMin = 1000.f; + float pullPowerRate = 75.f; +}; \ No newline at end of file diff --git a/patches/codehook.slpatch b/patches/codehook.slpatch index bd23a58..b61398c 100644 --- a/patches/codehook.slpatch +++ b/patches/codehook.slpatch @@ -99,13 +99,14 @@ B59E28 B seadPrintHook // sead::system::print // Pause Menu Changes -4EAEC4 B overrideNerveHook // makes any button on pause menu run a specific nerve +// 4EAEC4 B overrideNerveHook // makes any button on pause menu run a specific nerve 4EA104 MOV W2, #5 // update state count to account for new custom state 4EA1F0 BL initNerveStateHook // inits options nerve state and server config state 4EA174 MOV X0, X20 // moves StageSceneStatePauseMenu to first arg 4EA17C NOP // prevents first new of StageSceneStateOption 4EA1A8 BL initStateHook // inits StageSceneStateOption and StageSceneStateServerConfig 4EA1C0 NOP // prevents mStateOption ptr from being overriden +4EAFA4 B overrideHelpFadeNerve // Gravity hooks diff --git a/romfs/LayoutData/SardineIcon.szs b/romfs/LayoutData/SardineIcon.szs new file mode 100644 index 0000000..8776014 Binary files /dev/null and b/romfs/LayoutData/SardineIcon.szs differ diff --git a/romfs/LocalizedData/USen/MessageData/LayoutMessage.szs b/romfs/LocalizedData/USen/MessageData/LayoutMessage.szs new file mode 100644 index 0000000..aceb8ee Binary files /dev/null and b/romfs/LocalizedData/USen/MessageData/LayoutMessage.szs differ diff --git a/source/hooks.cpp b/source/hooks.cpp index 24d148f..cc4d117 100644 --- a/source/hooks.cpp +++ b/source/hooks.cpp @@ -78,13 +78,21 @@ bool registerShineToList(Shine* shineActor) { return al::isAlive(shineActor); } -void overrideNerveHook(StageSceneStatePauseMenu* thisPtr, al::Nerve* nrvSet) { +// void overrideNerveHook(StageSceneStatePauseMenu* thisPtr, al::Nerve* nrvSet) { - if (al::isPadHoldZL(-1)) { - al::setNerve(thisPtr, &nrvStageSceneStatePauseMenuServerConfig); - } else { - al::setNerve(thisPtr, nrvSet); - } +// if (al::isPadHoldZL(-1)) { +// al::setNerve(thisPtr, &nrvStageSceneStatePauseMenuServerConfig); +// } else { +// al::setNerve(thisPtr, nrvSet); +// } +// } + +void overrideHelpFadeNerve(StageSceneStatePauseMenu* thisPtr) +{ + // Set label in menu inside LocalizedData/lang/MessageData/LayoutData/Menu.msbt + thisPtr->exeServerConfig(); + al::setNerve(thisPtr, &nrvStageSceneStatePauseMenuServerConfig); + return; } StageSceneStateServerConfig *sceneStateServerConfig = nullptr; diff --git a/source/layouts/SardineIcon.cpp b/source/layouts/SardineIcon.cpp new file mode 100644 index 0000000..52bbb41 --- /dev/null +++ b/source/layouts/SardineIcon.cpp @@ -0,0 +1,136 @@ +#include "layouts/SardineIcon.h" +#include "al/string/StringTmp.h" +#include "al/util.hpp" +#include "logger.hpp" +#include "main.hpp" +#include "prim/seadSafeString.h" +#include "puppets/PuppetInfo.h" +#include "rs/util.hpp" +#include "server/Client.hpp" +#include "server/gamemode/GameModeTimer.hpp" +#include "server/snh/SardineMode.hpp" +#include +#include + +SardineIcon::SardineIcon(const char* name, const al::LayoutInitInfo& initInfo) + : al::LayoutActor(name) +{ + + al::initLayoutActor(this, initInfo, "SardineIcon", 0); + + mInfo = GameModeManager::instance()->getInfo(); + + initNerve(&nrvSardineIconEnd, 0); + + al::hidePane(this, "SoloIcon"); + al::hidePane(this, "PackIcon"); + + kill(); +} + +void SardineIcon::appear() +{ + + al::startAction(this, "Appear", 0); + + al::setNerve(this, &nrvSardineIconAppear); + + al::LayoutActor::appear(); +} + +bool SardineIcon::tryEnd() +{ + if (!al::isNerve(this, &nrvSardineIconEnd)) { + al::setNerve(this, &nrvSardineIconEnd); + return true; + } + return false; +} + +bool SardineIcon::tryStart() +{ + + if (!al::isNerve(this, &nrvSardineIconWait) && !al::isNerve(this, &nrvSardineIconAppear)) { + + appear(); + + return true; + } + + return false; +} + +void SardineIcon::exeAppear() +{ + if (al::isActionEnd(this, 0)) { + al::setNerve(this, &nrvSardineIconWait); + } +} + +void SardineIcon::exeWait() +{ + if (al::isFirstStep(this)) { + al::startAction(this, "Wait", 0); + } + + GameTime& curTime = mInfo->mHidingTime; + + if (curTime.mHours > 0) { + al::setPaneStringFormat(this, "TxtCounter", "%01d:%02d:%02d", curTime.mHours, curTime.mMinutes, + curTime.mSeconds); + } else { + al::setPaneStringFormat(this, "TxtCounter", "%02d:%02d", curTime.mMinutes, + curTime.mSeconds); + } + + int playerCount = Client::getMaxPlayerCount(); + + if (playerCount > 0) { + + char playerNameBuf[0x100] = { 0 }; // max of 16 player names if player name size is 0x10 + + sead::BufferedSafeStringBase playerList = sead::BufferedSafeStringBase(playerNameBuf, 0x200); + + if (mInfo->mIsIt) + playerList.appendWithFormat("%s\n", Client::instance()->getClientName()); + + for (size_t i = 0; i < playerCount; i++) { + PuppetInfo* curPuppet = Client::getPuppetInfo(i); + if (curPuppet && curPuppet->isConnected && curPuppet->isIt) { + playerList.appendWithFormat("%s\n", curPuppet->puppetName); + } + } + + al::setPaneStringFormat(this, "TxtPlayerList", playerList.cstr()); + } +} + +void SardineIcon::exeEnd() +{ + + if (al::isFirstStep(this)) { + al::startAction(this, "End", 0); + } + + if (al::isActionEnd(this, 0)) { + kill(); + } +} + +void SardineIcon::showSolo() +{ + al::hidePane(this, "PackIcon"); + al::showPane(this, "SoloIcon"); +} + +void SardineIcon::showPack() +{ + al::hidePane(this, "SoloIcon"); + al::showPane(this, "PackIcon"); +} + +namespace { +NERVE_IMPL(SardineIcon, Appear) +NERVE_IMPL(SardineIcon, Wait) +NERVE_IMPL(SardineIcon, End) +} \ No newline at end of file diff --git a/source/server/Client.cpp b/source/server/Client.cpp index 9f8f1c4..5635345 100644 --- a/source/server/Client.cpp +++ b/source/server/Client.cpp @@ -6,6 +6,7 @@ #include "logger.hpp" #include "packets/Packet.h" #include "server/hns/HideAndSeekMode.hpp" +#include "server/snh/SardineMode.hpp" SEAD_SINGLETON_DISPOSER_IMPL(Client) @@ -599,26 +600,45 @@ void Client::sendTagInfPacket() { Logger::log("Static Instance is Null!\n"); return; } + + GameMode curMode = GameModeManager::instance()->getGameMode(); + HideAndSeekMode* hsMode; + HideAndSeekInfo* hsInfo; + SardineMode* sarMode; + SardineInfo* sarInfo; - sead::ScopedCurrentHeapSetter setter(sInstance->mHeap); - - HideAndSeekMode* hsMode = GameModeManager::instance()->getMode(); - - if (!GameModeManager::instance()->isMode(GameMode::HIDEANDSEEK)) { - Logger::log("State is not Hide and Seek!\n"); - return; - } - - HideAndSeekInfo* curInfo = GameModeManager::instance()->getInfo(); + switch(GameModeManager::instance()->getGameMode()){ + case GameMode::HIDEANDSEEK: + hsMode = GameModeManager::instance()->getMode(); + hsInfo = GameModeManager::instance()->getInfo(); + break; + case GameMode::SARDINE: + sarMode = GameModeManager::instance()->getMode(); + sarInfo = GameModeManager::instance()->getInfo(); + break; + case GameMode::NONE: + Logger::log("Tag info packet has unknown gamemode!\n"); + return; + default: + Logger::log("Tag info packet has unknown gamemode!\n"); + return; + }; TagInf *packet = new TagInf(); packet->mUserID = sInstance->mUserID; - packet->isIt = hsMode->isPlayerIt(); + if(curMode == GameMode::HIDEANDSEEK){ + packet->isIt = hsMode->isPlayerIt(); + packet->minutes = hsInfo->mHidingTime.mMinutes; + packet->seconds = hsInfo->mHidingTime.mSeconds; + } + else if (curMode == GameMode::SARDINE){ + packet->isIt = sarMode->isPlayerIt(); + packet->minutes = sarInfo->mHidingTime.mMinutes; + packet->seconds = sarInfo->mHidingTime.mSeconds; + } - packet->minutes = curInfo->mHidingTime.mMinutes; - packet->seconds = curInfo->mHidingTime.mSeconds; packet->updateType = static_cast(TagUpdateType::STATE | TagUpdateType::TIME); sInstance->mSocket->queuePacket(packet); @@ -909,6 +929,24 @@ void Client::updateTagInfo(TagInf *packet) { } + if (packet->mUserID == mUserID && GameModeManager::instance()->isMode(GameMode::SARDINE)) { + + SardineMode* mMode = GameModeManager::instance()->getMode(); + SardineInfo* curInfo = GameModeManager::instance()->getInfo(); + + if (packet->updateType & TagUpdateType::STATE) { + mMode->setPlayerTagState(packet->isIt); + } + + if (packet->updateType & TagUpdateType::TIME) { + curInfo->mHidingTime.mSeconds = packet->seconds; + curInfo->mHidingTime.mMinutes = packet->minutes; + } + + return; + + } + PuppetInfo* curInfo = findPuppetInfo(packet->mUserID, false); if (!curInfo) { diff --git a/source/server/SocketClient.cpp b/source/server/SocketClient.cpp index 08d9349..5dbc782 100644 --- a/source/server/SocketClient.cpp +++ b/source/server/SocketClient.cpp @@ -176,7 +176,7 @@ bool SocketClient::recv() { Logger::enableName(); } - char* packetBuf = (char*)mHeap->alloc(fullSize); + char* packetBuf = (char*)malloc(fullSize); if (packetBuf) { @@ -192,7 +192,7 @@ bool SocketClient::recv() { if (result > 0) { valread += result; } else { - mHeap->free(packetBuf); + free(packetBuf); Logger::log("Packet Read Failed! Value: %d\nPacket Size: %d\nPacket Type: %s\n", result, header->mPacketSize, packetNames[header->mType]); return this->tryReconnect(); } @@ -203,7 +203,7 @@ bool SocketClient::recv() { if (!mRecvQueue.isFull()) { mRecvQueue.push((s64)packet, sead::MessageQueue::BlockType::NonBlocking); } else { - mHeap->free(packetBuf); + free(packetBuf); } } } else { @@ -336,14 +336,16 @@ void SocketClient::recvFunc() { bool SocketClient::queuePacket(Packet* packet) { if (socket_log_state == SOCKET_LOG_CONNECTED) { - mSendQueue.push((s64)packet, - sead::MessageQueue::BlockType::NonBlocking); // as this is non-blocking, it - // will always return true. - return true; - } else { - mHeap->free(packet); - return false; + if (!mSendQueue.isFull()) { + mSendQueue.push( + (s64)packet, + sead::MessageQueue::BlockType::NonBlocking); // as this is non-blocking, it + // will always return true. + return true; + } } + mHeap->free(packet); + return false; } void SocketClient::trySendQueue() { @@ -355,6 +357,6 @@ void SocketClient::trySendQueue() { mHeap->free(curPacket); } -Packet* SocketClient::tryGetPacket(sead::MessageQueue::BlockType blockType) { - return socket_log_state == SOCKET_LOG_CONNECTED ? (Packet*)mRecvQueue.pop(blockType) : nullptr; +Packet* SocketClient::tryGetPacket() { + return socket_log_state == SOCKET_LOG_CONNECTED ? (Packet*)mRecvQueue.pop(sead::MessageQueue::BlockType::Blocking) : nullptr; } \ No newline at end of file diff --git a/source/server/snh/SardineConfigMenu.cpp b/source/server/snh/SardineConfigMenu.cpp new file mode 100644 index 0000000..e36db26 --- /dev/null +++ b/source/server/snh/SardineConfigMenu.cpp @@ -0,0 +1,70 @@ +#include "server/snh/SardineConfigMenu.hpp" +#include "logger.hpp" +#include "server/Client.hpp" +#include "server/gamemode/GameModeManager.hpp" +#include "server/snh/SardineMode.hpp" +#include + +SardineConfigMenu::SardineConfigMenu() + : GameModeConfigMenu() +{ +} + +void SardineConfigMenu::initMenu(const al::LayoutInitInfo& initInfo) +{ +} + +const sead::WFixedSafeString<0x200>* SardineConfigMenu::getStringData() +{ + sead::SafeArray, mItemCount>* gamemodeConfigOptions = new sead::SafeArray, mItemCount>(); + + gamemodeConfigOptions->mBuffer[0].copy(u"Sardine Gravity On"); + gamemodeConfigOptions->mBuffer[1].copy(u"Sardine Gravity Off"); + gamemodeConfigOptions->mBuffer[2].copy(u"Enable Sardine Tether (Default)"); + gamemodeConfigOptions->mBuffer[3].copy(u"Disable Sardine Tether"); + + return gamemodeConfigOptions->mBuffer; +} + +bool SardineConfigMenu::updateMenu(int selectIndex) +{ + + SardineInfo* curMode = GameModeManager::instance()->getInfo(); + + Logger::log("Setting Gravity Mode.\n"); + + if (!curMode) { + Logger::log("Unable to Load Mode info!\n"); + return true; + } + + switch (selectIndex) { + case 0: { + if (GameModeManager::instance()->isMode(GameMode::SARDINE)) { + curMode->mIsUseGravity = true; + } + return true; + } + case 1: { + if (GameModeManager::instance()->isMode(GameMode::SARDINE)) { + curMode->mIsUseGravity = false; + } + return true; + } + case 2: { + if (GameModeManager::instance()->isMode(GameMode::SARDINE)) { + curMode->mIsTether = true; + } + return true; + } + case 3: { + if (GameModeManager::instance()->isMode(GameMode::SARDINE)) { + curMode->mIsTether = false; + } + return true; + } + default: + Logger::log("Failed to interpret Index!\n"); + return false; + } +} \ No newline at end of file diff --git a/source/server/snh/SardineMode.cpp b/source/server/snh/SardineMode.cpp new file mode 100644 index 0000000..24cf08f --- /dev/null +++ b/source/server/snh/SardineMode.cpp @@ -0,0 +1,235 @@ +#include "server/snh/SardineMode.hpp" +#include "al/async/FunctorV0M.hpp" +#include "al/util.hpp" +#include "al/util/ControllerUtil.h" +#include "al/util/LiveActorUtil.h" +#include "al/util/MathUtil.h" +#include "game/GameData/GameDataFunction.h" +#include "game/GameData/GameDataHolderAccessor.h" +#include "game/Layouts/CoinCounter.h" +#include "game/Layouts/MapMini.h" +#include "game/Player/PlayerActorBase.h" +#include "game/Player/PlayerActorHakoniwa.h" +#include "game/Player/PlayerFunction.h" +#include "heap/seadHeapMgr.h" +#include "layouts/HideAndSeekIcon.h" +#include "logger.hpp" +#include "math/seadVector.h" +#include "rs/util.hpp" +#include "server/Client.hpp" +#include "server/gamemode/GameModeBase.hpp" +#include "server/gamemode/GameModeFactory.hpp" +#include "server/gamemode/GameModeManager.hpp" +#include "server/gamemode/GameModeTimer.hpp" +#include +#include + +#include "basis/seadNew.h" +#include "server/snh/SardineConfigMenu.hpp" + +SardineMode::SardineMode(const char* name) + : GameModeBase(name) +{ +} + +void SardineMode::init(const GameModeInitInfo& info) +{ + mSceneObjHolder = info.mSceneObjHolder; + mMode = info.mMode; + mCurScene = (StageScene*)info.mScene; + mPuppetHolder = info.mPuppetHolder; + + GameModeInfoBase* curGameInfo = GameModeManager::instance()->getInfo(); + + sead::ScopedCurrentHeapSetter heapSetter(GameModeManager::instance()->getHeap()); + + if (curGameInfo) + Logger::log("Gamemode info found: %s %s\n", GameModeFactory::getModeString(curGameInfo->mMode), GameModeFactory::getModeString(info.mMode)); + else + Logger::log("No gamemode info found\n"); + if (curGameInfo && curGameInfo->mMode == mMode) { + sead::ScopedCurrentHeapSetter heapSetter(GameModeManager::getSceneHeap()); + mInfo = (SardineInfo*)curGameInfo; + mModeTimer = new GameModeTimer(mInfo->mHidingTime); + Logger::log("Reinitialized timer with time %d:%.2d\n", mInfo->mHidingTime.mMinutes, mInfo->mHidingTime.mSeconds); + } else { + if (curGameInfo) + delete curGameInfo; // attempt to destory previous info before creating new one + + mInfo = GameModeManager::instance()->createModeInfo(); + + mModeTimer = new GameModeTimer(); + } + sead::ScopedCurrentHeapSetter heapSetterr(GameModeManager::getSceneHeap()); + + mModeLayout = new SardineIcon("SardineIcon", *info.mLayoutInitInfo); + + mModeLayout->showSolo(); + + // mModeTimer->disableTimer(); +} + +void SardineMode::begin() +{ + mModeLayout->appear(); + + mIsFirstFrame = true; + + if (mInfo->mIsIt) { + mModeTimer->enableTimer(); + mModeLayout->showPack(); + } else { + mModeTimer->disableTimer(); + mModeLayout->showSolo(); + } + + CoinCounter* coinCollect = mCurScene->mSceneLayout->mCoinCollectLyt; + CoinCounter* coinCounter = mCurScene->mSceneLayout->mCoinCountLyt; + MapMini* compass = mCurScene->mSceneLayout->mMapMiniLyt; + al::SimpleLayoutAppearWaitEnd* playGuideLyt = mCurScene->mSceneLayout->mPlayGuideMenuLyt; + + if (coinCounter->mIsAlive) + coinCounter->tryEnd(); + if (coinCollect->mIsAlive) + coinCollect->tryEnd(); + if (compass->mIsAlive) + compass->end(); + if (playGuideLyt->mIsAlive) + playGuideLyt->end(); + + GameModeBase::begin(); +} + +void SardineMode::end() +{ + + mModeLayout->tryEnd(); + + mModeTimer->disableTimer(); + + CoinCounter* coinCollect = mCurScene->mSceneLayout->mCoinCollectLyt; + CoinCounter* coinCounter = mCurScene->mSceneLayout->mCoinCountLyt; + MapMini* compass = mCurScene->mSceneLayout->mMapMiniLyt; + al::SimpleLayoutAppearWaitEnd* playGuideLyt = mCurScene->mSceneLayout->mPlayGuideMenuLyt; + + if (!coinCounter->mIsAlive) + coinCounter->tryStart(); + if (!coinCollect->mIsAlive) + coinCollect->tryStart(); + if (!compass->mIsAlive) + compass->appearSlideIn(); + if (!playGuideLyt->mIsAlive) + playGuideLyt->appear(); + + GameModeBase::end(); +} + +void SardineMode::update() +{ + PlayerActorBase* playerBase = rs::getPlayerActor(mCurScene); + bool isYukimaru = !playerBase->getPlayerInfo(); // if PlayerInfo is a nullptr, that means we're dealing with the bound bowl racer + + float highPuppetDistance = -1.f; + int farPuppetID = -1; + bool isAnyIt = false; + + if (mIsFirstFrame) { + if (mInfo->mIsUseGravityCam && mTicket) + al::startCamera(mCurScene, mTicket, -1); + mIsFirstFrame = false; + } + + if (playerBase) { + for (size_t i = 0; i < mPuppetHolder->getSize(); i++) { + PuppetInfo* curInfo = Client::getPuppetInfo(i); + + if (!curInfo) { + Logger::log("Checking %d, hit bounds %d-%d\n", i, mPuppetHolder->getSize(), Client::getMaxPlayerCount()); + break; + } + + float pupDist = al::calcDistance(playerBase, curInfo->playerPos); + bool isPupInStage = al::isEqualString(curInfo->stageName, GameDataFunction::getCurrentStageName(mCurScene->mHolder)); + + if ((pupDist > highPuppetDistance || highPuppetDistance == -1) && isPupInStage && curInfo->isIt) { + highPuppetDistance = pupDist; + farPuppetID = i; + } + + if (curInfo->isIt) + isAnyIt = true; + + if (curInfo->isConnected && curInfo->isInSameStage && curInfo->isIt && !mInfo->mIsIt && !isYukimaru && pupDist < 300.f) { + if (((PlayerActorHakoniwa*)playerBase)->mDimKeeper->is2DModel == curInfo->is2D && !PlayerFunction::isPlayerDeadStatus(playerBase)) { + mInfo->mIsIt = true; + mModeTimer->enableTimer(); + mModeLayout->showPack(); + + Client::sendTagInfPacket(); + } + } + } + } + + mModeTimer->updateTimer(); + + if ((PlayerFunction::isPlayerDeadStatus(playerBase) || highPuppetDistance > pullDistanceMax) && mInfo->mIsIt) { + mInfo->mIsIt = false; + mModeTimer->disableTimer(); + mModeLayout->showSolo(); + + Client::sendTagInfPacket(); + } + + // Player pulling + if (highPuppetDistance >= pullDistanceMin && mInfo->mIsIt && farPuppetID != -1 && mInfo->mIsTether) { + sead::Vector3f target = Client::getPuppetInfo(farPuppetID)->playerPos; + sead::Vector3f* playerPos = al::getTransPtr(playerBase); + sead::Vector3f direction = target - *playerPos; + + al::normalize(&direction); + + playerPos->add(direction * ((al::calcDistance(playerBase, target) - pullDistanceMin) / pullPowerRate)); + } + + if (mInfo->mIsUseGravity && !isYukimaru) { + sead::Vector3f gravity; + if (rs::calcOnGroundNormalOrGravityDir(&gravity, playerBase, playerBase->getPlayerCollision())) { + gravity = -gravity; + al::normalize(&gravity); + al::setGravity(playerBase, gravity); + al::setGravity(((PlayerActorHakoniwa*)playerBase)->mHackCap, gravity); + } + + if (al::isPadHoldL(-1)) { + if (al::isPadTriggerRight(-1)) { + if (al::isActiveCamera(mTicket)) { + al::endCamera(mCurScene, mTicket, -1, false); + mInfo->mIsUseGravityCam = false; + } else { + al::startCamera(mCurScene, mTicket, -1); + mInfo->mIsUseGravityCam = true; + } + } + } else if (al::isPadTriggerZL(-1)) { + if (al::isPadTriggerLeft(-1)) { + killMainPlayer(((PlayerActorHakoniwa*)playerBase)); + } + } + } + + if (al::isPadTriggerUp(-1) && !al::isPadHoldZL(-1)) { + if (!mInfo->mIsIt && !isAnyIt) { + mInfo->mIsIt = true; + mModeTimer->enableTimer(); + mModeLayout->showPack(); + } else { + mInfo->mIsIt = false; + mModeTimer->disableTimer(); + mModeLayout->showSolo(); + } + Client::sendTagInfPacket(); + } + + mInfo->mHidingTime = mModeTimer->getTime(); +} \ No newline at end of file