Tarferi icon

Starcraft Emulator Trigger Core

Tarferi | PRO | 08/23/19 10:29:07 AM UTC | 0 ⭐ | 1136 👁️ | Never ⏰ | []
C++ |

8.83 KB

|

None

|

0 👍

/

0 👎

#include "TriggerCore.h"
 
 
 
TriggerCore::TriggerCore(EUDStarcraft* sc, char* data, unsigned int length) {
    this->data = data;
    this->length = length;
    this->sc = sc;
 
    this->sc->PlayersTriggerList[0].first = nullptr;
    this->sc->PlayersTriggerList[1].first = nullptr;
    this->sc->PlayersTriggerList[2].first = nullptr;
    this->sc->PlayersTriggerList[3].first = nullptr;
    this->sc->PlayersTriggerList[4].first = nullptr;
    this->sc->PlayersTriggerList[5].first = nullptr;
    this->sc->PlayersTriggerList[6].first = nullptr;
    this->sc->PlayersTriggerList[7].first = nullptr;
 
}
 
#define NODE_NEEDED EnabledFor(t, player) || EnabledFor(t, Players::AllPlayers) || EnabledFor(t, Players::Force1 + playerForces[player])
 
void createNodeIfNeeded(TriggerNode* nodes, unsigned int* freeNodeIndex, Trigger* t, unsigned int player, unsigned char* playerForces, TriggerList* PlayersTriggerList) {
    if (NODE_NEEDED) {
        TriggerList* lst = &(PlayersTriggerList[player]);
        TriggerNode* node = &(nodes[*freeNodeIndex]);
        *freeNodeIndex = (*freeNodeIndex) + 1;
        node->prev = nullptr;
        node->next = nullptr;
        memcpy(&(node->data), t->data, sizeof(TriggerData));
        if (lst->first == nullptr) { // First
            lst->first = node;
        } else { // Has prev
            node->prev = lst->last;
            node->prev->next = node;
        }
        lst->last = node;
    }
}
 
bool TriggerCore::construct() {
    char* localData = this->data;
 
    // Construct trigger array
    for (unsigned int i = 0; i < length / sizeof(TriggerData); i++) {
        Trigger* t = new Trigger(localData, i);
        localData += sizeof(TriggerData);
        if (!triggers.append(t)) {
            delete t;
            return false;
        }
    }
 
    // Calculate how many nodes it takes
    totalNodes = 0;
    unsigned char* playerForces = sc->playerForces;
    for (unsigned int i = 0; i < triggers.getSize(); i++) {
        Trigger* t = triggers.get(i);
        for (unsigned int player = 0; player < 8; player++) {
            if (NODE_NEEDED) {
                totalNodes++;
            }
        }
    }
 
    sc->firstNode = nullptr;
    sc->lastNode = nullptr;
 
    if (totalNodes > 0) { // Create nodes
 
        memset(sc->PlayersTriggerList, 0, sizeof(TriggerList) * 8);
        MALLOC_N(newNodes, TriggerNode, totalNodes, { return false; });
        nodes = newNodes;
 
        sc->firstNode = nodes;
        sc->lastNode = nodes + (sizeof(TriggerNode)*totalNodes);
 
        // Create trigger lists
        unsigned int currentNodeIndex = 0;
        for (unsigned int i = 0; i < triggers.getSize(); i++) {
            Trigger* t = triggers.get(i);
            createNodeIfNeeded(nodes, &currentNodeIndex, t, Players::Player1, sc->playerForces, sc->PlayersTriggerList);
            createNodeIfNeeded(nodes, &currentNodeIndex, t, Players::Player2, sc->playerForces, sc->PlayersTriggerList);
            createNodeIfNeeded(nodes, &currentNodeIndex, t, Players::Player3, sc->playerForces, sc->PlayersTriggerList);
            createNodeIfNeeded(nodes, &currentNodeIndex, t, Players::Player4, sc->playerForces, sc->PlayersTriggerList);
            createNodeIfNeeded(nodes, &currentNodeIndex, t, Players::Player5, sc->playerForces, sc->PlayersTriggerList);
            createNodeIfNeeded(nodes, &currentNodeIndex, t, Players::Player6, sc->playerForces, sc->PlayersTriggerList);
            createNodeIfNeeded(nodes, &currentNodeIndex, t, Players::Player7, sc->playerForces, sc->PlayersTriggerList);
            createNodeIfNeeded(nodes, &currentNodeIndex, t, Players::Player8, sc->playerForces, sc->PlayersTriggerList);
        }
    }
    return true;
}
 
inline bool TriggerCore::isNativeTrigger(TriggerNode* node) {
    return node >= nodes && node < nodes + ((sizeof(TriggerNode)*totalNodes));
}
 
TriggerCore::~TriggerCore() {
    for (unsigned int i = 0; i < triggers.getSize(); i++) {
        Trigger* trig = triggers.get(i);
        delete trig;
    }
    FREE_NOT_NULL(nodes);
    FREE_NOT_NULL(data);
}
 
TriggerCore * TriggerCore::get(char * file, EUDStarcraft* sc) {
    bool error = false;
    FILE* f;
    if (!fopen_s(&f, file, "rb")) {
        ReadBuffer rb(f, &error);
        fclose(f);
        if (error) {
            return nullptr;
        }
        unsigned int length = rb.getDataSize();
        char* data = (char*) rb.readArray(length, &error);
        if (error) {
            return nullptr;
        }
        TriggerCore* tc = new TriggerCore(sc, data, length);
        if (!tc->construct()) {
            delete tc;
            return nullptr;
        }
        return tc;
    }
    return nullptr;
}
 
void TriggerCore::run() {
 
    sc->load();
 
    bool _segFault = false;
    bool* segFault = &_segFault;
 
    FILE* f;
    if (fopen_s(&f, "..\\EUDEmulator\\exec.txt", "wb")) {
        return;
    }
 
    // Execute triggers in loops
    while(true) {
 
        TriggerNode* prev = nullptr;
 
        for (unsigned int playerTriggerIndex = 0; playerTriggerIndex < 8; playerTriggerIndex++) {
            sc->currentPlayerIndexForTriggers = playerTriggerIndex;
            if (sc->executePlayerLoop[playerTriggerIndex]) {
                TriggerList* triggers = &(sc->PlayersTriggerList[playerTriggerIndex]);
                TriggerNode* node = triggers->first;
 
                unsigned int triggersExecutedCounter = 0;
 
                while (node != nullptr) {
 
                    bool outputCurrentTrigger = false;
                    int triggerIndex = -1;
                    int triggerFlags = -1;
                    WriteBuffer conditionBuffer;
                    WriteBuffer actionBuffer;
 
                    if (!sc->isAllocated((unsigned int) node, sizeof(TriggerNode))) {
                        *segFault = true;
#ifdef TRIG_PRINT
                        OutputDebugStringA("\r\n\r\n =================== End of execution because of segfault of node =================== \r\n\r\n");
#endif
                    }
 
                    if (!(*segFault)) { // Node is valid
                        // Update current trigger
                        sc->currentTriggerNode = node;
                        triggersExecutedCounter++;
 
                        TriggerData* trigger = (TriggerData*)(&node->data);
                        triggerIndex = trigger->flags >> 16;
                        triggerFlags = trigger->flags & 0xffff;
 
                        if (Trigger::canBeExecutedNow(sc, trigger, &conditionBuffer, segFault)) { // Can be executed
                            SET_EXECUTE(trigger);
                        }
 
 
                        if (!(*segFault)) { // Conditions didn't cause segfault
                            if (HAS_EXECUTE(trigger)) { // Can be executed
                                outputCurrentTrigger = true;
                                CLEAR_EXECUTE(trigger); // Clear execution flag
                                bool stopTriggersForCurrentPlayer = false;
                                bool stopTriggersForAllPlayers = false;
                                Trigger::executeNow(sc, trigger, &actionBuffer, &stopTriggersForCurrentPlayer, &stopTriggersForAllPlayers, segFault);
 
                                if (!HAS_PRESERVE(trigger)) {
                                    SET_IGNORE_EXECUTION(trigger);
                                }
 
                                if (stopTriggersForCurrentPlayer) {
                                    sc->executePlayerLoop[playerTriggerIndex] = false;
                                }
                                if (stopTriggersForAllPlayers) {
                                    for (unsigned int playerIndex = 0; playerIndex < 8; playerIndex++) {
                                        sc->executePlayerLoop[playerIndex] = false;
                                    }
                                    break;
                                }
                            }
                        }
                    }
                        
#ifdef TRIG_PRINT
                    if (outputCurrentTrigger || (*segFault)) { // Output incomplete trigger causing segfault or any executed trigged
                        bool error = false;
                        conditionBuffer.writeByte(0, &error);
                        actionBuffer.writeByte(0, &error);
                        unsigned char* actData;
                        unsigned char* condData;
                        unsigned int actDataLen;
                        unsigned int condDataLen;
                        conditionBuffer.getWrittenData(&condData, &condDataLen);
                        actionBuffer.getWrittenData(&actData, &actDataLen);
                        char trigID[128];
                        if (isNativeTrigger(node)) {
                            sprintf_s(trigID, "%d (flags: %d), for player %d", triggerIndex, triggerFlags, playerTriggerIndex + 1);
                        } else { // Trigger outside of TRIG section
                            unsigned int offPtr = 0;
                            char* fmt = sc->getTriggerOrigin(node, &offPtr, segFault);
                            sprintf_s(trigID, "%s[%d] 0x%X (flags: %d), for player %d", fmt, offPtr, (unsigned int)node, triggerFlags, playerTriggerIndex + 1);
                        }
 
                        if (!outputCurrentTrigger) {
                            OutputDebugStringA("Following trigger was NOT executed\r\n");
                        }
                        if (*segFault) {
                            OutputDebugStringA("Following trigger caused segfault\r\n");
                        }
                        OutputDebugStringA("///////////////////// Conditions[");
                        OutputDebugStringA(trigID);
                        OutputDebugStringA("] ////////////////////\r\n");
                        OutputDebugStringA((char*)condData);
                        OutputDebugStringA("////////////////////// Actions[");
                        OutputDebugStringA(trigID);
                        OutputDebugStringA("] //////////////////////\r\n");
                        OutputDebugStringA((char*)actData);
                        OutputDebugStringA("///////////////////////////////////////////////////////////////////////////////////\r\n\r\n");
                    }
#endif
                        
                    if (*segFault) { // Break trigger loop for current player
                        break;
                    }
                    prev = node;
                    node = node->next;
                }
            }
            if (*segFault) { // Break trigger loop for all players
                break;
            }
        }
        if (*segFault) { // Stop triggers
            break;
        }
        OutputDebugStringA("\r\n\r\n ================== End of trigger loop =================\r\n\r\n");
        Sleep(500);
    }
 
    if (*segFault) {
        OutputDebugStringA("\r\n\r\n =================== End of execution because of segfault =================== \r\n\r\n");
    }
 
    fclose(f);
}

Comments