Skip to content

Commit

Permalink
Fully functional DeathLink implementation - But it's always on right now
Browse files Browse the repository at this point in the history
  • Loading branch information
NewSoupVi committed Mar 8, 2023
1 parent 61e44a0 commit bc50440
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 9 deletions.
14 changes: 14 additions & 0 deletions Source/Archipelago/APGameData.h
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,20 @@ const inline int AllPuzzles[]{
0x3D9A9,
};

const inline std::set<int> deathlinkExcludeList = {
0x0008F, // UTM Invisible Dots 1
0x0006B, // UTM Invisible Dots 2
0x0008B, // UTM Invisible Dots 3
0x0008C, // UTM Invisible Dots 4
0x0008A, // UTM Invisible Dots 5
0x00089, // UTM Invisible Dots 6
0x0006A, // UTM Invisible Dots 7
0x0006C, // UTM Invisible Dots 8
0x00027, // UTM Invisible Dots Symmetry 1
0x00028, // UTM Invisible Dots Symmetry 2
0x00029, // UTM Invisible Dots Symmetry 3
};

const inline std::set<int> allEPs = {
0x0332B, 0x03367, 0x28B8A, 0x037B6, 0x037B2, 0x000F7, 0x3351D, 0x0053C
, 0x00771, 0x335C8, 0x335C9, 0x337F8, 0x037BB, 0x220E4, 0x220E5, 0x334B9
Expand Down
40 changes: 37 additions & 3 deletions Source/Archipelago/APRandomizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,15 @@ bool APRandomizer::Connect(std::string& server, std::string& user, std::string&
for (auto& [key, val] : slotData["ep_to_name"].items()) {
int sideId = std::stoul(key, nullptr, 16);

epToName.insert({ sideId, val });
entityToName.insert({ sideId, val });
}
}

if (slotData.contains("entity_to_name")) {
for (auto& [key, val] : slotData["entity_to_name"].items()) {
int sideId = std::stoul(key, nullptr, 16);

entityToName.insert({ sideId, val });
}
}

Expand Down Expand Up @@ -235,6 +243,10 @@ bool APRandomizer::Connect(std::string& server, std::string& user, std::string&
}
}

std::list<std::string> newTags = { "DeathLink" };

ap->ConnectUpdate(NULL, newTags);

connected = true;
hasConnectionResult = true;
});
Expand All @@ -251,6 +263,28 @@ bool APRandomizer::Connect(std::string& server, std::string& user, std::string&
ClientWindow::get()->showMessageBox("Connection failed: " + errorString);
});

ap->set_bounced_handler([&](nlohmann::json packet) {
std::list<std::string> tags = packet["tags"];

bool deathlink = (std::find(tags.begin(), tags.end(), "DeathLink") != tags.end());

if (deathlink) {
auto data = packet["data"];
std::string cause = "";
if (data.contains("cause")) {
cause = data["cause"];
}
std::string source = "";
if (data.contains("source")) {
source = data["source"];
}

double timestamp = data["time"];

async->ProcessDeathLink(timestamp, cause, source);
}
});

ap->set_retrieved_handler([&](const std::map <std::string, nlohmann::json> response) {
for (auto [key, value] : response) {
if(key.find("WitnessLaser") != std::string::npos) async->HandleLaserResponse(key, value, Collect);
Expand Down Expand Up @@ -500,15 +534,15 @@ void APRandomizer::Init() {
}

void APRandomizer::GenerateNormal() {
async = new APWatchdog(ap, panelIdToLocationId, FinalPanel, panelLocker, epToName, audioLogMessages, obeliskSideIDsToEPHexes, EPShuffle, PuzzleRandomization, &state, solveModeSpeedFactor);
async = new APWatchdog(ap, panelIdToLocationId, FinalPanel, panelLocker, entityToName, audioLogMessages, obeliskSideIDsToEPHexes, EPShuffle, PuzzleRandomization, &state, solveModeSpeedFactor);
SeverDoors();

if (DisableNonRandomizedPuzzles)
panelLocker->DisableNonRandomizedPuzzles(disabledPanels, doorsActuallyInTheItemPool);
}

void APRandomizer::GenerateHard() {
async = new APWatchdog(ap, panelIdToLocationId, FinalPanel, panelLocker, epToName, audioLogMessages, obeliskSideIDsToEPHexes, EPShuffle, PuzzleRandomization, &state, solveModeSpeedFactor);
async = new APWatchdog(ap, panelIdToLocationId, FinalPanel, panelLocker, entityToName, audioLogMessages, obeliskSideIDsToEPHexes, EPShuffle, PuzzleRandomization, &state, solveModeSpeedFactor);
SeverDoors();

//Mess with Town targets
Expand Down
2 changes: 1 addition & 1 deletion Source/Archipelago/APRandomizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class APRandomizer {

std::map<int, std::set<int>> obeliskSideIDsToEPHexes;
std::set<int> precompletedLocations;
std::map<int, std::string> epToName;
std::map<int, std::string> entityToName;

class APClient* ap = NULL;
class APWatchdog* async;
Expand Down
48 changes: 44 additions & 4 deletions Source/Archipelago/APWatchdog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ APWatchdog::APWatchdog(APClient* client, std::map<int, int> mapping, int lastPan
state = s;
EPShuffle = ep;
obeliskHexToEPHexes = o;
epToName = epn;
entityToName = epn;
solveModeSpeedFactor = smsf;

speedTime = ReadPanelData<float>(0x3D9A7, VIDEO_STATUS_COLOR);
Expand Down Expand Up @@ -1563,8 +1563,8 @@ void APWatchdog::LookingAtObelisk() {
}
}

if (epToName.count(lookingAtEP)) {
hudManager->setWorldMessage(epToName[lookingAtEP]);
if (entityToName.count(lookingAtEP)) {
hudManager->setWorldMessage(entityToName[lookingAtEP]);
}

return;
Expand Down Expand Up @@ -1659,15 +1659,55 @@ void APServerPoller::action() {

void APWatchdog::CheckDeathLink() {
if (mostRecentActivePanelId == -1 || !actuallyEveryPanel.count(mostRecentActivePanelId)) return;
if (deathlinkExcludeList.count(mostRecentActivePanelId)) return;

int newState = ReadPanelData<int>(mostRecentActivePanelId, FLASH_MODE);

if (mostRecentPanelState != newState) {
mostRecentPanelState = newState;

if (newState == 2) {
TriggerPowerSurge();
SendDeathLink();
hudManager->queueBannerMessage("Death Sent.");
}
}
}

void APWatchdog::SendDeathLink()
{
auto now = std::chrono::system_clock::now();
double nowDouble = (double)std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count() / 1000;

std::string entityName = std::to_string(mostRecentActivePanelId);

if (entityToName.count(mostRecentActivePanelId)) {
entityName = entityToName[mostRecentActivePanelId];
}

deathLinkTimestamps.insert(nowDouble);

auto data = nlohmann::json{
{"time", nowDouble},
{"cause", "Input an incorrect solution to " + entityName + "."},
{"source", ap->get_player_alias(ap->get_player_number())}
} ;
ap->Bounce(data, {}, {}, {"DeathLink"});
}

void APWatchdog::ProcessDeathLink(double time, std::string cause, std::string source) {
TriggerPowerSurge();

if (deathLinkTimestamps.count(time)) return;

std::string firstSentence = "Received Death.";
std::string secondSentence = "";

if (source != "") {
firstSentence = "Received Death from " + source + ".";
}
if (cause != "") {
secondSentence = " Reason: " + cause;
}

hudManager->queueBannerMessage(firstSentence + secondSentence);
}
7 changes: 6 additions & 1 deletion Source/Archipelago/APWatchdog.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class APWatchdog : public Watchdog {

void InfiniteChallenge(bool enable);

void ProcessDeathLink(double time, std::string cause, std::string source);

bool processingItemMessages = false;
bool newItemsJustIn = false;

Expand Down Expand Up @@ -85,6 +87,8 @@ class APWatchdog : public Watchdog {
bool hasPowerSurge = false;
std::chrono::system_clock::time_point powerSurgeStartTime;

std::set<double> deathLinkTimestamps;

const float baseSpeed = 2.0f;

bool laserRequirementMet = false;
Expand All @@ -108,6 +112,7 @@ class APWatchdog : public Watchdog {
void CheckEPSkips();

void CheckDeathLink();
void SendDeathLink();

void QueueItemMessages();

Expand Down Expand Up @@ -177,7 +182,7 @@ class APWatchdog : public Watchdog {
std::map<int, std::pair<std::string, int64_t>> audioLogMessages = {};
std::map<int, std::set<int>> obeliskHexToEPHexes = {};
std::map<int, int> obeliskHexToAmountOfEPs = {};
std::map<int, std::string> epToName = {};
std::map<int, std::string> entityToName = {};

std::vector<float> lastMousePosition = { 0,0,0 };
float dogFrames = 0.0f;
Expand Down

0 comments on commit bc50440

Please sign in to comment.