mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-01-07 11:58:13 -05:00
Start effects
This commit is contained in:
parent
791f7774a5
commit
1bebf6ad91
1048
libultraship/libultraship/Lib/SDL/SDL2/SDL_net.h
Normal file
1048
libultraship/libultraship/Lib/SDL/SDL2/SDL_net.h
Normal file
File diff suppressed because it is too large
Load Diff
93
libultraship/libultraship/Lib/SDL/SDL2/SDLnetsys.h
Normal file
93
libultraship/libultraship/Lib/SDL/SDL2/SDLnetsys.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
SDL_net: An example cross-platform network library for use with SDL
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* Include normal system headers */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef _WIN32_WCE
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
/* Include system network headers */
|
||||
#if defined(__WIN32__) || defined(WIN32)
|
||||
#define __USE_W32_SOCKETS
|
||||
#ifdef _WIN64
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <winsock.h>
|
||||
/* NOTE: windows socklen_t is signed
|
||||
* and is defined only for winsock2. */
|
||||
typedef int socklen_t;
|
||||
#endif /* W64 */
|
||||
#include <iphlpapi.h>
|
||||
#else /* UNIX */
|
||||
#include <sys/types.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#ifndef __BEOS__
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netdb.h>
|
||||
#endif /* WIN32 */
|
||||
|
||||
/* FIXME: What platforms need this? */
|
||||
#if 0
|
||||
typedef Uint32 socklen_t;
|
||||
#endif
|
||||
|
||||
/* System-dependent definitions */
|
||||
#ifndef __USE_W32_SOCKETS
|
||||
#ifdef __OS2__
|
||||
#define closesocket soclose
|
||||
#else /* !__OS2__ */
|
||||
#define closesocket close
|
||||
#endif /* __OS2__ */
|
||||
#define SOCKET int
|
||||
#define INVALID_SOCKET -1
|
||||
#define SOCKET_ERROR -1
|
||||
#endif /* __USE_W32_SOCKETS */
|
||||
|
||||
#ifdef __USE_W32_SOCKETS
|
||||
#define SDLNet_GetLastError WSAGetLastError
|
||||
#define SDLNet_SetLastError WSASetLastError
|
||||
#ifndef EINTR
|
||||
#define EINTR WSAEINTR
|
||||
#endif
|
||||
#else
|
||||
int SDLNet_GetLastError(void);
|
||||
void SDLNet_SetLastError(int err);
|
||||
#endif
|
||||
|
53
libultraship/libultraship/Lib/SDL/SDL2/chat.h
Normal file
53
libultraship/libultraship/Lib/SDL/SDL2/chat.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
CHAT: A chat client/server using the SDL example network library
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* Convert four letters into a number */
|
||||
#define MAKE_NUM(A, B, C, D) (((A+B)<<8)|(C+D))
|
||||
|
||||
/* Defines for the chat client */
|
||||
#define CHAT_SCROLLBACK 512 /* Save 512 lines in scrollback */
|
||||
#define CHAT_PROMPT "> "
|
||||
#define CHAT_PACKETSIZE 256 /* Maximum length of a message */
|
||||
|
||||
/* Defines shared between the server and client */
|
||||
#define CHAT_PORT MAKE_NUM('C','H','A','T')
|
||||
|
||||
/* The protocol between the chat client and server */
|
||||
#define CHAT_HELLO 0 /* 0+Port+len+name */
|
||||
#define CHAT_HELLO_PORT 1
|
||||
#define CHAT_HELLO_NLEN CHAT_HELLO_PORT+2
|
||||
#define CHAT_HELLO_NAME CHAT_HELLO_NLEN+1
|
||||
#define CHAT_ADD 1 /* 1+N+IP+Port+len+name */
|
||||
#define CHAT_ADD_SLOT 1
|
||||
#define CHAT_ADD_HOST CHAT_ADD_SLOT+1
|
||||
#define CHAT_ADD_PORT CHAT_ADD_HOST+4
|
||||
#define CHAT_ADD_NLEN CHAT_ADD_PORT+2
|
||||
#define CHAT_ADD_NAME CHAT_ADD_NLEN+1
|
||||
#define CHAT_DEL 2 /* 2+N */
|
||||
#define CHAT_DEL_SLOT 1
|
||||
#define CHAT_DEL_LEN CHAT_DEL_SLOT+1
|
||||
#define CHAT_BYE 255 /* 255 */
|
||||
#define CHAT_BYE_LEN 1
|
||||
|
||||
/* The maximum number of people who can talk at once */
|
||||
#define CHAT_MAXPEOPLE 10
|
BIN
libultraship/libultraship/Lib/SDL/lib/x64/SDL2_net_debug_x64.lib
Normal file
BIN
libultraship/libultraship/Lib/SDL/lib/x64/SDL2_net_debug_x64.lib
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
libultraship/libultraship/Lib/SDL/lib/x86/SDL2_net_debug_x86.lib
Normal file
BIN
libultraship/libultraship/Lib/SDL/lib/x86/SDL2_net_debug_x86.lib
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -222,6 +222,13 @@ set(Header_Files__soh__Enhancements__custom_message
|
||||
|
||||
source_group("Header Files\\soh\\Enhancements\\custom-message" FILES ${Header_Files__soh__Enhancements__custom_message})
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
set(Header_Files__soh__Enhancements__crowd_control
|
||||
"soh/Enhancements/crowd-control/CrowdControl.h"
|
||||
)
|
||||
source_group("Header Files\\soh\\Enhancements\\crowd-control" FILES ${Header_Files__soh__Enhancements__crowd_control})
|
||||
endif()
|
||||
|
||||
set(Source_Files__soh
|
||||
"soh/GbiWrap.cpp"
|
||||
"soh/OTRAudio.h"
|
||||
@ -339,6 +346,13 @@ set(Source_Files__soh__Enhancements__custom_message
|
||||
|
||||
source_group("Source Files\\soh\\Enhancements\\custom-message" FILES ${Source_Files__soh__Enhancements__custom_message})
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
set(Source_Files__soh__Enhancements__crowd_control
|
||||
"soh/Enhancements/crowd-control/CrowdControl.cpp"
|
||||
)
|
||||
source_group("Source Files\\soh\\Enhancements\\crowd-control" FILES ${Source_Files__soh__Enhancements__crowd_control})
|
||||
endif()
|
||||
|
||||
set(Source_Files__src__boot
|
||||
"src/boot/assert.c"
|
||||
"src/boot/boot_main.c"
|
||||
@ -1548,6 +1562,7 @@ set(ALL_FILES
|
||||
${Header_Files__soh__Enhancements__randomizer}
|
||||
${Header_Files__soh__Enhancements__randomizer__3drando}
|
||||
${Header_Files__soh__Enhancements__custom_message}
|
||||
${Header_Files__soh__Enhancements__crowd_control}
|
||||
${Source_Files__soh}
|
||||
${Source_Files__soh__Enhancements}
|
||||
${Source_Files__soh__Enhancements__cosmetics}
|
||||
@ -1557,6 +1572,7 @@ set(ALL_FILES
|
||||
${Source_Files__soh__Enhancements__randomizer__3drando__hint_list}
|
||||
${Source_Files__soh__Enhancements__randomizer__3drando__location_access}
|
||||
${Source_Files__soh__Enhancements__custom_message}
|
||||
${Source_Files__soh__Enhancements__crowd_control}
|
||||
${Source_Files__src__boot}
|
||||
${Source_Files__src__buffers}
|
||||
${Source_Files__src__code}
|
||||
@ -1663,7 +1679,8 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
"$<$<CONFIG:Debug>:"
|
||||
"_DEBUG;"
|
||||
"_CRT_SECURE_NO_WARNINGS;"
|
||||
"ENABLE_DX11"
|
||||
"ENABLE_DX11;"
|
||||
"ENABLE_CROWD_CONTROL"
|
||||
">"
|
||||
"$<$<CONFIG:Release>:"
|
||||
"NDEBUG"
|
||||
|
@ -481,3 +481,6 @@
|
||||
/* 0x01D4 */ DEFINE_ACTOR(En_Mm2, ACTOR_EN_MM2, ALLOCTYPE_NORMAL)
|
||||
/* 0x01D5 */ DEFINE_ACTOR(Bg_Jya_Block, ACTOR_BG_JYA_BLOCK, ALLOCTYPE_NORMAL)
|
||||
/* 0x01D6 */ DEFINE_ACTOR(Obj_Warp2block, ACTOR_OBJ_WARP2BLOCK, ALLOCTYPE_NORMAL)
|
||||
#ifdef __ENABLE_CROWD_CONTROL__
|
||||
/* 0x01D7 */ DEFINE_ACTOR(Obj_CrowdControl, ACTOR_CROWD_CONTROL, ALLOCTYPE_NORMAL)
|
||||
#endif
|
||||
|
217
soh/soh/Enhancements/crowd-control/CrowdControl.cpp
Normal file
217
soh/soh/Enhancements/crowd-control/CrowdControl.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
#ifdef ENABLE_CROWD_CONTROL
|
||||
|
||||
#include "CrowdControl.h"
|
||||
#include "Cvar.h"
|
||||
#include "Lib/json.hpp"
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <regex>
|
||||
|
||||
#include "soh/Enhancements/debugconsole.h"
|
||||
|
||||
extern "C" u8 ExecuteEffect(const char* effectId, uint32_t value);
|
||||
extern "C" void RemoveEffect(const char* effectId);
|
||||
|
||||
namespace Ship {
|
||||
namespace CrowdControl {
|
||||
void CrowdControl::InitCrowdControl() {
|
||||
SDLNet_Init();
|
||||
|
||||
if (SDLNet_ResolveHost(&ip, "127.0.0.1", 43384) == -1) {
|
||||
printf("SDLNet_ResolveHost: %s\n", SDLNet_GetError());
|
||||
}
|
||||
|
||||
ccThreadReceive = std::thread(&CrowdControl::ReceiveFromCrowdControl, this);
|
||||
}
|
||||
|
||||
void CrowdControl::RunCrowdControl(CCPacket* packet) {
|
||||
u8 paused = 0;
|
||||
|
||||
while (connected) {
|
||||
u8 anotherEffect = 0;
|
||||
|
||||
nlohmann::json dataSend;
|
||||
|
||||
dataSend["id"] = packet->packetId;
|
||||
dataSend["type"] = 0;
|
||||
|
||||
dataSend["timeRemaining"] = packet->timeRemaining;
|
||||
|
||||
for (CCPacket* pack : receivedCommands) {
|
||||
if (pack != packet && pack->effectCategory == packet->effectCategory && pack->packetId < packet->packetId) {
|
||||
anotherEffect = 1;
|
||||
dataSend["status"] = EffectResult::Retry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u8 returnSuccess = 0;
|
||||
if (anotherEffect == 0) {
|
||||
returnSuccess = ExecuteEffect(packet->effectType.c_str(), packet->effectValue);
|
||||
dataSend["status"] = returnSuccess == 1 ? EffectResult::Success : returnSuccess == 2 ? EffectResult::Failure : EffectResult::Retry;
|
||||
}
|
||||
|
||||
std::string jsonResponse = dataSend.dump();
|
||||
SDLNet_TCP_Send(tcpsock, const_cast<char*> (jsonResponse.data()), jsonResponse.size() + 1);
|
||||
|
||||
if (anotherEffect == 0) {
|
||||
if (returnSuccess == 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (returnSuccess == 1) {
|
||||
if (paused && packet->timeRemaining > 0) {
|
||||
paused = 0;
|
||||
nlohmann::json dataSend;
|
||||
dataSend["id"] = packet->packetId;
|
||||
dataSend["type"] = 0;
|
||||
dataSend["timeRemaining"] = packet->timeRemaining;
|
||||
dataSend["status"] = EffectResult::Resumed;
|
||||
|
||||
std::string jsonResponse = dataSend.dump();
|
||||
SDLNet_TCP_Send(tcpsock, const_cast<char*> (jsonResponse.data()), jsonResponse.size() + 1);
|
||||
}
|
||||
|
||||
if (packet->timeRemaining <= 0) {
|
||||
receivedCommands.erase(std::remove(receivedCommands.begin(), receivedCommands.end(), packet), receivedCommands.end());
|
||||
RemoveEffect(packet->effectType.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
packet->timeRemaining -= 1000;
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
else if (returnSuccess == 0 && paused == 0 && packet->timeRemaining > 0) {
|
||||
paused = 1;
|
||||
|
||||
nlohmann::json dataSend;
|
||||
dataSend["id"] = packet->packetId;
|
||||
dataSend["type"] = 0;
|
||||
dataSend["timeRemaining"] = packet->timeRemaining;
|
||||
dataSend["status"] = EffectResult::Paused;
|
||||
|
||||
std::string jsonResponse = dataSend.dump();
|
||||
SDLNet_TCP_Send(tcpsock, const_cast<char*> (jsonResponse.data()), jsonResponse.size() + 1);
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
else {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CrowdControl::ReceiveFromCrowdControl()
|
||||
{
|
||||
printf("Waiting for a connection from Crowd Control...");
|
||||
|
||||
while (!connected && CVar_GetS32("gCrowdControl", 0) == 1) {
|
||||
tcpsock = SDLNet_TCP_Open(&ip);
|
||||
|
||||
if (tcpsock) {
|
||||
connected = true;
|
||||
printf("Connected to Crowd Control!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (connected && CVar_GetS32("gCrowdControl", 0) == 1 && tcpsock) {
|
||||
int len = SDLNet_TCP_Recv(tcpsock, &received, 512);
|
||||
|
||||
if (!len || !tcpsock || len == -1) {
|
||||
printf("SDLNet_TCP_Recv: %s\n", SDLNet_GetError());
|
||||
break;
|
||||
}
|
||||
|
||||
nlohmann::json dataReceived = nlohmann::json::parse(received);
|
||||
|
||||
CCPacket* packet = new CCPacket();
|
||||
packet->packetId = dataReceived["id"];
|
||||
packet->effectValue = dataReceived["type"];
|
||||
packet->effectType = dataReceived["code"].get<std::string>();
|
||||
|
||||
if (strcmp(packet->effectType.c_str(), "high_gravity") == 0 ||
|
||||
strcmp(packet->effectType.c_str(), "low_gravity") == 0) {
|
||||
packet->effectCategory = "gravity";
|
||||
packet->timeRemaining = 30000;
|
||||
}
|
||||
else if (strcmp(packet->effectType.c_str(), "defense_modifier") == 0) {
|
||||
packet->effectCategory = "defense";
|
||||
packet->timeRemaining = 30000;
|
||||
}
|
||||
else if (strcmp(packet->effectType.c_str(), "giant_link") == 0 ||
|
||||
strcmp(packet->effectType.c_str(), "minish_link") == 0 ||
|
||||
strcmp(packet->effectType.c_str(), "invisible") == 0 ||
|
||||
strcmp(packet->effectType.c_str(), "paper_link") == 0) {
|
||||
packet->effectCategory = "link_size";
|
||||
packet->timeRemaining = 30000;
|
||||
}
|
||||
else if (strcmp(packet->effectType.c_str(), "freeze") == 0 ||
|
||||
strcmp(packet->effectType.c_str(), "damage") == 0 ||
|
||||
strcmp(packet->effectType.c_str(), "heal") == 0 ||
|
||||
strcmp(packet->effectType.c_str(), "knockback") == 0 ||
|
||||
strcmp(packet->effectType.c_str(), "electrocute") == 0 ||
|
||||
strcmp(packet->effectType.c_str(), "burn") == 0) {
|
||||
packet->effectCategory = "link_damage";
|
||||
}
|
||||
else if (strcmp(packet->effectType.c_str(), "hover_boots") == 0 ||
|
||||
strcmp(packet->effectType.c_str(), "iron_boots") == 0) {
|
||||
packet->effectCategory = "boots";
|
||||
packet->timeRemaining = 30000;
|
||||
}
|
||||
else if (strcmp(packet->effectType.c_str(), "add_heart_container") == 0 ||
|
||||
strcmp(packet->effectType.c_str(), "remove_heart_container") == 0) {
|
||||
packet->effectCategory = "heart_container";
|
||||
}
|
||||
else if (strcmp(packet->effectType.c_str(), "no_ui") == 0) {
|
||||
packet->effectCategory = "ui";
|
||||
}
|
||||
else if (strcmp(packet->effectType.c_str(), "fill_magic") == 0 ||
|
||||
strcmp(packet->effectType.c_str(), "empty_magic") == 0) {
|
||||
packet->effectCategory = "magic";
|
||||
}
|
||||
else if (strcmp(packet->effectType.c_str(), "ohko") == 0) {
|
||||
packet->effectCategory = "ohko";
|
||||
}
|
||||
else if (strcmp(packet->effectType.c_str(), "pacifist") == 0) {
|
||||
packet->effectCategory = "pacifist";
|
||||
}
|
||||
else if (strcmp(packet->effectType.c_str(), "rainstorm") == 0) {
|
||||
packet->effectCategory = "weather";
|
||||
}
|
||||
else if (strcmp(packet->effectType.c_str(), "reverse") == 0) {
|
||||
packet->effectCategory = "controls";
|
||||
}
|
||||
else if (strcmp(packet->effectType.c_str(), "rupees") == 0) {
|
||||
packet->effectCategory = "rupees";
|
||||
}
|
||||
else if (strcmp(packet->effectType.c_str(), "speed") == 0) {
|
||||
packet->effectCategory = "speed";
|
||||
}
|
||||
else if (strcmp(packet->effectType.c_str(), "wallmaster") == 0 ||
|
||||
strcmp(packet->effectType.c_str(), "cucco") == 0) {
|
||||
packet->effectCategory = "spawn";
|
||||
}
|
||||
else {
|
||||
packet->effectCategory = "none";
|
||||
packet->timeRemaining = 0;
|
||||
}
|
||||
|
||||
receivedCommands.push_back(packet);
|
||||
std::thread t = std::thread(&CrowdControl::RunCrowdControl, this, packet);
|
||||
t.detach();
|
||||
}
|
||||
|
||||
if (connected) {
|
||||
SDLNet_TCP_Close(tcpsock);
|
||||
SDLNet_Quit();
|
||||
connected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
89
soh/soh/Enhancements/crowd-control/CrowdControl.h
Normal file
89
soh/soh/Enhancements/crowd-control/CrowdControl.h
Normal file
@ -0,0 +1,89 @@
|
||||
#ifdef ENABLE_CROWD_CONTROL
|
||||
|
||||
#ifndef _CROWDCONTROL_C
|
||||
#define _CROWDCONTROL_C
|
||||
#endif
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
#include <SDL2/SDL_net.h>
|
||||
#include <cstdint>
|
||||
#include <thread>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <future>
|
||||
|
||||
namespace Ship {
|
||||
namespace CrowdControl {
|
||||
typedef struct CCPacket {
|
||||
uint32_t packetId;
|
||||
std::string effectType;
|
||||
uint32_t effectValue;
|
||||
std::string effectCategory;
|
||||
long timeRemaining;
|
||||
} CCPacket;
|
||||
|
||||
enum EffectResult {
|
||||
/// <summary>The effect executed successfully.</summary>
|
||||
Success = 0x00,
|
||||
/// <summary>The effect failed to trigger, but is still available for use. Viewer(s) will be refunded. You probably don't want this.</summary>
|
||||
Failure = 0x01,
|
||||
/// <summary>Same as <see cref="Failure"/> but the effect is no longer available for use for the remainder of the game. You probably don't want this.</summary>
|
||||
Unavailable = 0x02,
|
||||
/// <summary>The effect cannot be triggered right now, try again in a few seconds. This is the "normal" failure response.</summary>
|
||||
Retry = 0x03,
|
||||
/// <summary>INTERNAL USE ONLY. The effect has been queued for execution after the current one ends.</summary>
|
||||
Queue = 0x04,
|
||||
/// <summary>INTERNAL USE ONLY. The effect triggered successfully and is now active until it ends.</summary>
|
||||
Running = 0x05,
|
||||
/// <summary>The timed effect has been paused and is now waiting.</summary>
|
||||
Paused = 0x06,
|
||||
/// <summary>The timed effect has been resumed and is counting down again.</summary>
|
||||
Resumed = 0x07,
|
||||
/// <summary>The timed effect has finished.</summary>
|
||||
Finished = 0x08,
|
||||
/// <summary>The processor isn't ready to start or has shut down.</summary>
|
||||
NotReady = 0xFF
|
||||
};
|
||||
|
||||
enum ResponseType {
|
||||
EffectRequest = 0x00,
|
||||
Login = 0xF0,
|
||||
LoginSuccess = 0xF1,
|
||||
Disconnect = 0xFE,
|
||||
KeepAlive = 0xFF
|
||||
};
|
||||
|
||||
struct Response {
|
||||
int id;
|
||||
EffectResult status;
|
||||
long timeRemaining;
|
||||
ResponseType type = ResponseType::EffectRequest;
|
||||
};
|
||||
|
||||
class CrowdControl {
|
||||
private:
|
||||
std::thread ccThreadReceive;
|
||||
|
||||
TCPsocket tcpsock;
|
||||
IPaddress ip;
|
||||
|
||||
bool connected;
|
||||
|
||||
char received[512];
|
||||
|
||||
std::vector<CCPacket*> currentCommands;
|
||||
std::vector<CCPacket*> receivedCommands;
|
||||
|
||||
void RunCrowdControl(CCPacket* packet);
|
||||
void ReceiveFromCrowdControl();
|
||||
|
||||
public:
|
||||
void InitCrowdControl();
|
||||
};
|
||||
}
|
||||
} // namespace Ship
|
||||
#endif
|
@ -33,6 +33,14 @@ extern GlobalContext* gGlobalCtx;
|
||||
|
||||
#define CMD_REGISTER SohImGui::BindCmd
|
||||
|
||||
uint32_t defenseModifier;
|
||||
uint32_t giantLink;
|
||||
uint32_t minishLink;
|
||||
uint32_t highGravity;
|
||||
uint32_t resetLinkScale;
|
||||
uint32_t noUi;
|
||||
uint32_t invisibleLink;
|
||||
|
||||
static bool ActorSpawnHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
if ((args.size() != 9) && (args.size() != 3) && (args.size() != 6)) {
|
||||
SohImGui::console->SendErrorMessage("Not enough arguments passed to actorspawn");
|
||||
@ -373,6 +381,25 @@ static bool StateSlotSelectHandler(std::shared_ptr<Ship::Console> Console, const
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static bool InvisibleHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
if (args.size() != 2) {
|
||||
SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
bool invisible;
|
||||
|
||||
try {
|
||||
invisible = std::stoi(args[1], nullptr, 10);
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::console->SendErrorMessage("[SOH] Invisible value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
invisibleLink = invisible;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define VARTYPE_INTEGER 0
|
||||
#define VARTYPE_FLOAT 1
|
||||
#define VARTYPE_STRING 2
|
||||
@ -466,47 +493,62 @@ void DebugConsole_Init(void) {
|
||||
CMD_REGISTER("rupee", { RuppeHandler, "Set your rupee counter.", {
|
||||
{"amount", Ship::ArgumentType::NUMBER }
|
||||
}});
|
||||
CMD_REGISTER("bItem", { BHandler, "Set an item to the B button.", { { "Item ID", Ship::ArgumentType::NUMBER } } });
|
||||
CMD_REGISTER("health", { SetPlayerHealthHandler, "Set the health of the player.", { { "health", Ship::ArgumentType::NUMBER }
|
||||
CMD_REGISTER("bItem", { BHandler, "Set an item to the B button.", {
|
||||
{ "Item ID", Ship::ArgumentType::NUMBER }
|
||||
}});
|
||||
CMD_REGISTER("spawn", { ActorSpawnHandler, "Spawn an actor.", { { "actor_id", Ship::ArgumentType::NUMBER },
|
||||
{ "data", Ship::ArgumentType::NUMBER },
|
||||
{ "x", Ship::ArgumentType::PLAYER_POS, true },
|
||||
{ "y", Ship::ArgumentType::PLAYER_POS, true },
|
||||
{ "z", Ship::ArgumentType::PLAYER_POS, true },
|
||||
{ "rx", Ship::ArgumentType::PLAYER_ROT, true },
|
||||
{ "ry", Ship::ArgumentType::PLAYER_ROT, true },
|
||||
{ "rz", Ship::ArgumentType::PLAYER_ROT, true }
|
||||
CMD_REGISTER("health", { SetPlayerHealthHandler, "Set the health of the player.", {
|
||||
{ "health", Ship::ArgumentType::NUMBER }
|
||||
}});
|
||||
CMD_REGISTER("pos", { SetPosHandler, "Sets the position of the player.", { { "x", Ship::ArgumentType::PLAYER_POS, true },
|
||||
{ "y", Ship::ArgumentType::PLAYER_POS, true },
|
||||
{ "z", Ship::ArgumentType::PLAYER_POS, true }
|
||||
CMD_REGISTER("spawn", { ActorSpawnHandler, "Spawn an actor.", {
|
||||
{ "actor_id", Ship::ArgumentType::NUMBER },
|
||||
{ "data", Ship::ArgumentType::NUMBER },
|
||||
{ "x", Ship::ArgumentType::PLAYER_POS, true },
|
||||
{ "y", Ship::ArgumentType::PLAYER_POS, true },
|
||||
{ "z", Ship::ArgumentType::PLAYER_POS, true },
|
||||
{ "rx", Ship::ArgumentType::PLAYER_ROT, true },
|
||||
{ "ry", Ship::ArgumentType::PLAYER_ROT, true },
|
||||
{ "rz", Ship::ArgumentType::PLAYER_ROT, true }
|
||||
}});
|
||||
CMD_REGISTER("pos", { SetPosHandler, "Sets the position of the player.", {
|
||||
{ "x", Ship::ArgumentType::PLAYER_POS, true },
|
||||
{ "y", Ship::ArgumentType::PLAYER_POS, true },
|
||||
{ "z", Ship::ArgumentType::PLAYER_POS, true }
|
||||
}});
|
||||
CMD_REGISTER("set", { SetCVarHandler, "Sets a console variable.", {
|
||||
{ "varName", Ship::ArgumentType::TEXT },
|
||||
{ "varValue", Ship::ArgumentType::TEXT }
|
||||
}});
|
||||
CMD_REGISTER("get", { GetCVarHandler, "Gets a console variable.", {
|
||||
{ "varName", Ship::ArgumentType::TEXT }
|
||||
}});
|
||||
CMD_REGISTER("set", { SetCVarHandler,
|
||||
"Sets a console variable.",
|
||||
{ { "varName", Ship::ArgumentType::TEXT }, { "varValue", Ship::ArgumentType::TEXT } } });
|
||||
CMD_REGISTER("get", { GetCVarHandler, "Gets a console variable.", { { "varName", Ship::ArgumentType::TEXT } } });
|
||||
CMD_REGISTER("reset", { ResetHandler, "Resets the game." });
|
||||
CMD_REGISTER("ammo", { AmmoHandler, "Changes ammo of an item.",
|
||||
{ { "item", Ship::ArgumentType::TEXT }, { "count", Ship::ArgumentType::NUMBER } } });
|
||||
CMD_REGISTER("ammo", { AmmoHandler, "Changes ammo of an item.", {
|
||||
{ "item", Ship::ArgumentType::TEXT },
|
||||
{ "count", Ship::ArgumentType::NUMBER }
|
||||
}});
|
||||
|
||||
CMD_REGISTER("bottle", { BottleHandler,
|
||||
"Changes item in a bottle slot.",
|
||||
{ { "item", Ship::ArgumentType::TEXT }, { "slot", Ship::ArgumentType::NUMBER } } });
|
||||
CMD_REGISTER("bottle", { BottleHandler, "Changes item in a bottle slot.", {
|
||||
{ "item", Ship::ArgumentType::TEXT },
|
||||
{ "slot", Ship::ArgumentType::NUMBER }
|
||||
}});
|
||||
|
||||
CMD_REGISTER("item", { ItemHandler,
|
||||
"Sets item ID in arg 1 into slot arg 2. No boundary checks. Use with caution.",
|
||||
{ { "slot", Ship::ArgumentType::NUMBER }, { "item id", Ship::ArgumentType::NUMBER } } });
|
||||
CMD_REGISTER("entrance", { EntranceHandler,
|
||||
"Sends player to the entered entrance (hex)",
|
||||
{ { "entrance", Ship::ArgumentType::NUMBER } } });
|
||||
CMD_REGISTER("item", { ItemHandler, "Sets item ID in arg 1 into slot arg 2. No boundary checks. Use with caution.", {
|
||||
{ "slot", Ship::ArgumentType::NUMBER },
|
||||
{ "item id", Ship::ArgumentType::NUMBER }
|
||||
}});
|
||||
CMD_REGISTER("entrance", { EntranceHandler, "Sends player to the entered entrance (hex)", {
|
||||
{ "entrance", Ship::ArgumentType::NUMBER }
|
||||
}});
|
||||
|
||||
CMD_REGISTER("save_state", { SaveStateHandler, "Save a state." });
|
||||
CMD_REGISTER("load_state", { LoadStateHandler, "Load a state." });
|
||||
CMD_REGISTER("set_slot", { StateSlotSelectHandler, "Selects a SaveState slot", { {
|
||||
"Slot number",
|
||||
Ship::ArgumentType::NUMBER,
|
||||
}
|
||||
} });
|
||||
CMD_REGISTER("set_slot", { StateSlotSelectHandler, "Selects a SaveState slot", {
|
||||
{ "Slot number", Ship::ArgumentType::NUMBER, }
|
||||
}});
|
||||
|
||||
CMD_REGISTER("invisible", { InvisibleHandler, "Toggles invisibility.", {
|
||||
{ "invisible", Ship::ArgumentType::NUMBER }
|
||||
}});
|
||||
|
||||
CVar_Load();
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern uint32_t defenseModifier;
|
||||
extern uint32_t giantLink;
|
||||
extern uint32_t minishLink;
|
||||
extern uint32_t highGravity;
|
||||
extern uint32_t resetLinkScale;
|
||||
extern uint32_t noUi;
|
||||
extern uint32_t invisibleLink;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
void DebugConsole_Init(void);
|
||||
|
@ -4,8 +4,10 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "soh/Enhancements/gameconsole.h"
|
||||
#include "soh/Enhancements/debugconsole.h"
|
||||
#include "../libultraship/ImGuiImpl.h"
|
||||
#include "soh/frame_interpolation.h"
|
||||
#include <overlays/actors/ovl_En_Niw/z_en_niw.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@ -1527,6 +1529,158 @@ void Gameplay_Main(GameState* thisx) {
|
||||
|
||||
}
|
||||
|
||||
u8 PlayerGrounded(Player* player) {
|
||||
return (player->actor.world.pos.y - player->actor.floorHeight) == 0;
|
||||
}
|
||||
|
||||
extern func_80AB70A0(EnNiw* this, GlobalContext* globalCtx);
|
||||
|
||||
void RemoveEffect(const char* effectId) {
|
||||
if (gGlobalCtx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player* player = GET_PLAYER(gGlobalCtx);
|
||||
|
||||
if (player != NULL) {
|
||||
if (strcmp(effectId, "giant_link") == 0) {
|
||||
giantLink = 0;
|
||||
resetLinkScale = 1;
|
||||
return;
|
||||
} else if (strcmp(effectId, "minish_link") == 0) {
|
||||
minishLink = 0;
|
||||
resetLinkScale = 1;
|
||||
} else if (strcmp(effectId, "defense_modifier") == 0) {
|
||||
defenseModifier = 0;
|
||||
return;
|
||||
} else if (strcmp(effectId, "iron_boots") == 0 || strcmp(effectId, "hover_boots") == 0) {
|
||||
player->currentBoots = PLAYER_BOOTS_KOKIRI;
|
||||
Inventory_ChangeEquipment(EQUIP_BOOTS, PLAYER_BOOTS_KOKIRI + 1);
|
||||
Player_SetBootData(gGlobalCtx, player);
|
||||
return;
|
||||
} else if (strcmp(effectId, "high_gravity") == 0 || strcmp(effectId, "low_gravity") == 0) {
|
||||
highGravity = 0;
|
||||
return;
|
||||
} else if (strcmp(effectId, "no_ui") == 0) {
|
||||
noUi = 0;
|
||||
return;
|
||||
} else if (strcmp(effectId, "invisible") == 0) {
|
||||
invisibleLink = 0;
|
||||
player->actor.shape.shadowDraw = ActorShadow_DrawFeet;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u8 ExecuteEffect(const char* effectId, uint32_t value) {
|
||||
if (gGlobalCtx == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Player* player = GET_PLAYER(gGlobalCtx);
|
||||
|
||||
if (player != NULL) {
|
||||
if (strcmp(effectId, "add_heart_container") == 0) {
|
||||
if (gSaveContext.healthCapacity >= 0x140) {
|
||||
return 2;
|
||||
}
|
||||
gSaveContext.healthCapacity += 0x10;
|
||||
return 1;
|
||||
} else if (strcmp(effectId, "remove_heart_container") == 0) {
|
||||
if ((gSaveContext.healthCapacity - 0x10) <= 0) {
|
||||
return 2;
|
||||
}
|
||||
gSaveContext.healthCapacity -= 0x10;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (player != NULL && !Player_InBlockingCsMode(gGlobalCtx, player) && gGlobalCtx->pauseCtx.state == 0) {
|
||||
if (strcmp(effectId, "high_gravity") == 0) {
|
||||
highGravity = 1;
|
||||
return 1;
|
||||
} else if (strcmp(effectId, "low_gravity") == 0) {
|
||||
highGravity = 2;
|
||||
return 1;
|
||||
} else if (strcmp(effectId, "giant_link") == 0) {
|
||||
giantLink = 1;
|
||||
return 1;
|
||||
} else if (strcmp(effectId, "minish_link") == 0) {
|
||||
minishLink = 1;
|
||||
return 1;
|
||||
} else if (strcmp(effectId, "defense_modifier") == 0) {
|
||||
defenseModifier = value;
|
||||
return 1;
|
||||
} else if (strcmp(effectId, "kill") == 0) {
|
||||
if (PlayerGrounded(player)) {
|
||||
gSaveContext.health = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
} else if (strcmp(effectId, "cucco") == 0) {
|
||||
EnNiw* cucco =
|
||||
(EnNiw*)Actor_Spawn(&gGlobalCtx->actorCtx, gGlobalCtx, ACTOR_EN_NIW, player->actor.world.pos.x,
|
||||
player->actor.world.pos.y, player->actor.world.pos.z, 0, 0, 0, 0);
|
||||
cucco->actionFunc = func_80AB70A0;
|
||||
return 1;
|
||||
} else if (strcmp(effectId, "damage") == 0) {
|
||||
Health_ChangeBy(gGlobalCtx, -value * 16);
|
||||
func_80837C0C(gGlobalCtx, player, 0, 0, 0, 0, 0);
|
||||
player->invincibilityTimer = 28;
|
||||
return 1;
|
||||
} else if (strcmp(effectId, "heal") == 0) {
|
||||
Health_ChangeBy(gGlobalCtx, value * 16);
|
||||
return 1;
|
||||
} else if (strcmp(effectId, "freeze") == 0) {
|
||||
if (PlayerGrounded(player)) {
|
||||
func_80837C0C(gGlobalCtx, player, 3, 0, 0, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
} else if (strcmp(effectId, "knockback") == 0) {
|
||||
func_8002F71C(gGlobalCtx, &player->actor, value * 5, player->actor.world.rot.y + 0x8000, value * 5);
|
||||
return 1;
|
||||
} else if (strcmp(effectId, "burn") == 0) {
|
||||
if (PlayerGrounded(player)) {
|
||||
for (int i = 0; i < 18; i++) {
|
||||
player->flameTimers[i] = Rand_S16Offset(0, 200);
|
||||
}
|
||||
player->isBurning = true;
|
||||
func_80837C0C(gGlobalCtx, player, 0, 0, 0, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
} else if (strcmp(effectId, "electrocute") == 0) {
|
||||
if (PlayerGrounded(player)) {
|
||||
func_80837C0C(gGlobalCtx, player, 4, 0, 0, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
} else if (strcmp(effectId, "iron_boots") == 0) {
|
||||
player->currentBoots = PLAYER_BOOTS_IRON;
|
||||
Inventory_ChangeEquipment(EQUIP_BOOTS, PLAYER_BOOTS_IRON + 1);
|
||||
Player_SetBootData(gGlobalCtx, player);
|
||||
return 1;
|
||||
} else if (strcmp(effectId, "hover_boots") == 0) {
|
||||
player->currentBoots = PLAYER_BOOTS_HOVER;
|
||||
Inventory_ChangeEquipment(EQUIP_BOOTS, PLAYER_BOOTS_HOVER + 1);
|
||||
Player_SetBootData(gGlobalCtx, player);
|
||||
return 1;
|
||||
} else if (strcmp(effectId, "wallmaster") == 0) {
|
||||
Actor_Spawn(&gGlobalCtx->actorCtx, gGlobalCtx, ACTOR_EN_WALLMAS, player->actor.world.pos.x, player->actor.world.pos.y, player->actor.world.pos.z, 0, 0, 0, 0);
|
||||
return 1;
|
||||
} else if (strcmp(effectId, "no_ui") == 0) {
|
||||
noUi = 1;
|
||||
return 1;
|
||||
} else if (strcmp(effectId, "invisible") == 0) {
|
||||
invisibleLink = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// original name: "Game_play_demo_mode_check"
|
||||
s32 Gameplay_InCsMode(GlobalContext* globalCtx) {
|
||||
return (globalCtx->csCtx.state != CS_STATE_IDLE) || Player_InCsMode(globalCtx);
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include "objects/object_triforce_spot/object_triforce_spot.h"
|
||||
#include "overlays/actors/ovl_Demo_Effect/z_demo_effect.h"
|
||||
|
||||
#include "soh/Enhancements/debugconsole.h"
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ u8 flag;
|
||||
/* 0x02 */ u16 textId;
|
||||
@ -1037,6 +1039,11 @@ s32 func_80090014(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* p
|
||||
}
|
||||
}
|
||||
|
||||
if (invisibleLink) {
|
||||
this->actor.shape.shadowDraw = NULL;
|
||||
*dList = NULL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "objects/object_link_child/object_link_child.h"
|
||||
#include "textures/icon_item_24_static/icon_item_24_static.h"
|
||||
#include <soh/Enhancements/custom-message/CustomMessageTypes.h>
|
||||
#include "soh/Enhancements/debugconsole.h"
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ u8 itemId;
|
||||
@ -11105,6 +11106,35 @@ void Player_Update(Actor* thisx, GlobalContext* globalCtx) {
|
||||
MREG(53) = this->actor.world.pos.y;
|
||||
MREG(54) = this->actor.world.pos.z;
|
||||
MREG(55) = this->actor.world.rot.y;
|
||||
|
||||
// Crowd Control
|
||||
|
||||
if (giantLink == 1) {
|
||||
this->actor.scale.x = 0.025f;
|
||||
this->actor.scale.y = 0.025f;
|
||||
this->actor.scale.z = 0.025f;
|
||||
}
|
||||
|
||||
if (minishLink == 1) {
|
||||
this->actor.scale.x = 0.001f;
|
||||
this->actor.scale.y = 0.001f;
|
||||
this->actor.scale.z = 0.001f;
|
||||
}
|
||||
|
||||
if (resetLinkScale == 1) {
|
||||
this->actor.scale.x = 0.01f;
|
||||
this->actor.scale.y = 0.01f;
|
||||
this->actor.scale.z = 0.01f;
|
||||
resetLinkScale = 0;
|
||||
}
|
||||
|
||||
if (highGravity == 1) {
|
||||
this->actor.gravity = -4.0f;
|
||||
}
|
||||
|
||||
if (highGravity == 2) {
|
||||
this->actor.gravity = -0.3f;
|
||||
}
|
||||
}
|
||||
|
||||
static struct_80858AC8 D_80858AC8;
|
||||
|
Loading…
Reference in New Issue
Block a user