diff --git a/src/game/engine/foot.cpp b/src/game/engine/foot.cpp index f1634c52..cc79ebbe 100644 --- a/src/game/engine/foot.cpp +++ b/src/game/engine/foot.cpp @@ -1569,3 +1569,36 @@ BOOL FootClass::Is_On_Priority_Mission() { return m_Mission == MISSION_ENTER; } + +void FootClass::Queue_Navigation_List(target_t target) +{ +#ifndef CHRONOSHIFT_STANDALONE + void (*func)(FootClass *, target_t) = reinterpret_cast(0x004C35D0); + func(this, target); +#else + int i; + if (target != 0) { + for (i = 0; i < NAV_LENGTH && m_NavList[i] != 0; ++i); + if (target != As_Target() || i <= 0) { + if (i == 0) { + m_Bit2_4 = false; + } + if (i < NAV_LENGTH) { + m_NavList[i] = target; + } + } else { + m_Bit2_4 = true; + } + if (m_NavCom == 0 && Mission == MISSION_GUARD) { + Enter_Idle_Mode(); + } + } +#endif +} + +void FootClass::Clear_Navigation_List() +{ + for (int i = 0; i < NAV_LENGTH; ++i) { + m_NavList[i] = 0; + } +} diff --git a/src/game/engine/foot.h b/src/game/engine/foot.h index f25416ba..c576795c 100644 --- a/src/game/engine/foot.h +++ b/src/game/engine/foot.h @@ -123,6 +123,12 @@ class FootClass : public TechnoClass FacingType Get_Path_Facing(int index) const { return m_Paths[index]; } target_t Nav_Com() const { return m_NavCom; } + void Set_To_Scatter(BOOL state) { m_ToScatter = state; } + void Set_In_Formation(BOOL state) { m_InFormation = state; } + void Set_Team_Speed(SpeedType speed) { m_TeamSpeed = speed; } + void Set_Team_Max_Speed(MPHType mph) { m_TeamMaxSpeed = mph; } + void Set_Suspended_NavCom(target_t target) { m_SuspendedNavCom = target; } + static int Point_Relative_To_Line(int px, int py, int sx, int sy, int ex, int ey); PathType *Find_Path_Wrapper(cell_t dest, FacingType *buffer, int length, MoveType move); @@ -132,6 +138,8 @@ class FootClass : public TechnoClass #endif const fixed_t &Get_Speed_Multiplier() const { return m_SpeedMult; } + void Queue_Navigation_List(target_t target); + void Clear_Navigation_List(); const GamePtr &Get_Team() const { return m_Team; } protected: diff --git a/src/game/engine/gameevent.cpp b/src/game/engine/gameevent.cpp index 4bdfc18d..e24d5b94 100644 --- a/src/game/engine/gameevent.cpp +++ b/src/game/engine/gameevent.cpp @@ -3,8 +3,9 @@ * * @author CCHyper * @author OmniBlade + * @author tomsons26 * - * @brief + * @brief * * @copyright Chronoshift is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -14,21 +15,34 @@ * LICENSE */ #include "gameevent.h" +#include "anim.h" #include "animtype.h" +#include "building.h" +#include "callback.h" #include "coord.h" +#include "foot.h" +#include "gameoptions.h" #include "globals.h" #include "house.h" +#include "iomap.h" #include "mission.h" -#include - -#define EVENT_captainslog_debug(x, ...) \ - /*if ( g_Debug_Print_Events )*/ \ +#include "msgbox.h" +#include "rules.h" +#include "saveload.h" +#include "scenario.h" +#include "session.h" +#include "team.h" +#include "techno.h" +#include "theme.h" +#include "vessel.h" + +#define EVENT_DEBUG_LOG(x, ...) /*if ( g_Debug_Print_Events )*/ \ { \ captainslog_debug(x, ##__VA_ARGS__); \ } -GameEventClass::EventInfoStruct GameEventClass::s_EventTypeList[EVENT_COUNT] = { - { "EMPTY", 0 },// No extra data. +GameEventClass::EventInfoStruct GameEventClass::EventTypeList[EVENT_COUNT] = { + { "EMPTY", 0 }, // No extra data. { "ALLY", sizeof(GameEventClass::HouseEventStruct) }, { "MEGAMISSION", sizeof(GameEventClass::MegaMissionEventStruct) }, { "MEGAMISSION_F", sizeof(GameEventClass::MegaMissionFEventStruct) }, @@ -36,7 +50,7 @@ GameEventClass::EventInfoStruct GameEventClass::s_EventTypeList[EVENT_COUNT] = { { "SCATTER", sizeof(GameEventClass::WhomEventStruct) }, { "DESTRUCT", 0 }, // No extra data. { "DEPLOY", 0 }, // No extra data. - { "PLACE", 3 }, + { "PLACE", sizeof(GameEventClass::RTTICellEventStruct) }, { "OPTIONS", 0 }, // No extra data. { "GAMESPEED", sizeof(GameEventClass::GameSpeedEventStruct) }, { "PRODUCE", sizeof(GameEventClass::RTTIHeapIDEventStruct) }, @@ -50,36 +64,29 @@ GameEventClass::EventInfoStruct GameEventClass::s_EventTypeList[EVENT_COUNT] = { { "SELL", sizeof(GameEventClass::WhomEventStruct) }, { "SELLCELL", sizeof(GameEventClass::CellEventStruct) }, { "SPECIAL", sizeof(GameEventClass::SpecialEventStruct) }, - { "FRAME_SYNC", 0 }, // Should be "sizeof(GameEventClass::FrameEventStruct)" + { "FRAME_SYNC", 0 }, // No extra data. { "MESSAGE", 0 }, // No extra data. - { "RESPONSE_TIME", sizeof(GameEventClass::TimeEventStruct) }, + { "RESPONSE_TIME", sizeof(GameEventClass::ResponseTimeEventStruct) }, { "FRAME_INFO", sizeof(GameEventClass::FrameEventStruct) }, { "SAVEGAME", 0 }, // No extra data. { "ARCHIVE", sizeof(GameEventClass::WhomTargetEventStruct) }, - { "ADDPLAYER", 4 }, // TODO + { "ADDPLAYER", 4 }, // original table has it as 4 but the event is actually 8 { "TIMING", sizeof(GameEventClass::TimingEventStruct) }, - { "PROCESS_TIME", 2 }, + { "PROCESS_TIME", sizeof(GameEventClass::ProcessTimeEventStruct) }, { "PROPOSE_DRAW", 0 }, // No extra data. { "RETRACT_DRAW", 0 } // No extra data. }; -GameEventClass::GameEventClass() : - m_Type(EVENT_EMPTY), - m_EventFrame(g_GameFrame), - m_HouseID(0), - m_IsExecuted(false) +GameEventClass::GameEventClass() : m_Type(EVENT_EMPTY), m_EventFrame(g_GameFrame), m_HouseID(0), m_IsExecuted(false) { // Removed, as this is used at the default constructor, so it will fire a lot of times... - // EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); + // EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); memset(&m_EventData, 0, sizeof(m_EventData)); } GameEventClass::GameEventClass(const GameEventClass &that) : - m_Type(that.m_Type), - m_EventFrame(that.m_EventFrame), - m_HouseID(that.m_HouseID), - m_IsExecuted(that.m_IsExecuted) + m_Type(that.m_Type), m_EventFrame(that.m_EventFrame), m_HouseID(that.m_HouseID), m_IsExecuted(that.m_IsExecuted) { memcpy(&m_EventData, &that.m_EventData, sizeof(m_EventData)); } @@ -97,23 +104,17 @@ GameEventClass &GameEventClass::operator=(const GameEventClass &that) } GameEventClass::GameEventClass(GameEventType type) : - m_Type(type), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(type), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); memset(&m_EventData, 0, sizeof(m_EventData)); } GameEventClass::GameEventClass(GameEventType type, cell_t cell) : - m_Type(type), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(type), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); memset(&m_EventData, 0, sizeof(m_EventData)); @@ -121,12 +122,9 @@ GameEventClass::GameEventClass(GameEventType type, cell_t cell) : } GameEventClass::GameEventClass(GameEventType type, unsigned int gamespeed) : - m_Type(type), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(type), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); memset(&m_EventData, 0, sizeof(m_EventData)); @@ -134,12 +132,9 @@ GameEventClass::GameEventClass(GameEventType type, unsigned int gamespeed) : } GameEventClass::GameEventClass(GameEventType type, HousesType house) : - m_Type(type), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(type), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); memset(&m_EventData, 0, sizeof(m_EventData)); @@ -147,12 +142,9 @@ GameEventClass::GameEventClass(GameEventType type, HousesType house) : } GameEventClass::GameEventClass(GameEventType type, RTTIType rtti) : - m_Type(type), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(type), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); memset(&m_EventData, 0, sizeof(m_EventData)); @@ -160,12 +152,9 @@ GameEventClass::GameEventClass(GameEventType type, RTTIType rtti) : } GameEventClass::GameEventClass(GameEventType type, RTTIType rtti, unsigned int heap_id) : - m_Type(type), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(type), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); memset(&m_EventData, 0, sizeof(m_EventData)); @@ -174,12 +163,9 @@ GameEventClass::GameEventClass(GameEventType type, RTTIType rtti, unsigned int h } GameEventClass::GameEventClass(GameEventType type, RTTIType rtti, cell_t cell) : - m_Type(type), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(type), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); memset(&m_EventData, 0, sizeof(m_EventData)); @@ -188,26 +174,20 @@ GameEventClass::GameEventClass(GameEventType type, RTTIType rtti, cell_t cell) : } GameEventClass::GameEventClass(GameEventType type, SpecialWeaponType special, cell_t cell) : - m_Type(type), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(type), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); memset(&m_EventData, 0, sizeof(m_EventData)); - m_EventData.u_SpecialPlace.m_Special = special; + m_EventData.u_SpecialPlace.m_SpecialWeapon = special; m_EventData.u_SpecialPlace.m_Cell = cell; } GameEventClass::GameEventClass(GameEventType type, void *a2, unsigned long a3) : - m_Type(type), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(type), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); memset(&m_EventData, 0, sizeof(m_EventData)); @@ -215,12 +195,9 @@ GameEventClass::GameEventClass(GameEventType type, void *a2, unsigned long a3) : } GameEventClass::GameEventClass(GameEventType type, TargetClass whom) : - m_Type(type), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(type), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); memset(&m_EventData, 0, sizeof(m_EventData)); @@ -228,12 +205,9 @@ GameEventClass::GameEventClass(GameEventType type, TargetClass whom) : } GameEventClass::GameEventClass(GameEventType type, TargetClass whom, TargetClass target) : - m_Type(type), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(type), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); memset(&m_EventData, 0, sizeof(m_EventData)); @@ -242,12 +216,9 @@ GameEventClass::GameEventClass(GameEventType type, TargetClass whom, TargetClass } GameEventClass::GameEventClass(GameEventType type, AnimType anim, HousesType owner, coord_t coord) : - m_Type(type), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(type), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating '%s' event. Anim:%s.", + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating '%s' event. Anim:%s.", Name_From(m_Type), AnimTypeClass::Name_From(anim)); @@ -259,12 +230,9 @@ GameEventClass::GameEventClass(GameEventType type, AnimType anim, HousesType own } GameEventClass::GameEventClass(GameEventType type, unsigned int crc, unsigned short cmd_count, unsigned char delay) : - m_Type(type), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(type), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); memset(&m_EventData, 0, sizeof(m_EventData)); @@ -274,12 +242,9 @@ GameEventClass::GameEventClass(GameEventType type, unsigned int crc, unsigned sh } GameEventClass::GameEventClass(GameEventType type, unsigned short desired_frame_rate, unsigned short max_ahead) : - m_Type(type), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(type), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); memset(&m_EventData, 0, sizeof(m_EventData)); @@ -288,12 +253,9 @@ GameEventClass::GameEventClass(GameEventType type, unsigned short desired_frame_ } GameEventClass::GameEventClass(TargetClass whom, MissionType mission, TargetClass target, TargetClass dest) : - m_Type(EVENT_MEGAMISSION), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(EVENT_MEGAMISSION), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating EVENT_MEGAMISSION event."); + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating EVENT_MEGAMISSION event."); memset(&m_EventData, 0, sizeof(m_EventData)); @@ -305,12 +267,9 @@ GameEventClass::GameEventClass(TargetClass whom, MissionType mission, TargetClas GameEventClass::GameEventClass( TargetClass whom, MissionType mission, TargetClass target, TargetClass dest, SpeedType speed, MPHType max_speed) : - m_Type(EVENT_MEGAMISSION_F), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(EVENT_MEGAMISSION_F), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating EVENT_MEGAMISSION_F event."); + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating EVENT_MEGAMISSION_F event."); memset(&m_EventData, 0, sizeof(m_EventData)); @@ -323,26 +282,20 @@ GameEventClass::GameEventClass( } GameEventClass::GameEventClass(SpecialClass special) : - m_Type(EVENT_SPECIAL), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(EVENT_SPECIAL), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); + EVENT_DEBUG_LOG("GameEventClass::GameEventClass() - Creating '%s' event.", Name_From(m_Type)); memset(&m_EventData, 0, sizeof(m_EventData)); - s_Special = special; + m_EventData.u_Special = special; } GameEventClass::GameEventClass(AnimType anim, HousesType owner, coord_t coord) : - m_Type(EVENT_ANIMATION), - m_EventFrame(g_GameFrame), - m_HouseID(g_PlayerPtr->Get_Heap_ID()), - m_IsExecuted(false) + m_Type(EVENT_ANIMATION), m_EventFrame(g_GameFrame), m_HouseID(g_PlayerPtr->Get_Heap_ID()), m_IsExecuted(false) { - EVENT_captainslog_debug( - "GameEventClass::GameEventClass() - Creating ANIMATION event. Anim:%s.\n", AnimTypeClass::Name_From(anim)); + EVENT_DEBUG_LOG( + "GameEventClass::GameEventClass() - Creating ANIMATION event. Anim:%s.", AnimTypeClass::Name_From(anim)); memset(&m_EventData, 0, sizeof(m_EventData)); @@ -353,132 +306,505 @@ GameEventClass::GameEventClass(AnimType anim, HousesType owner, coord_t coord) : void GameEventClass::Execute() { - EVENT_captainslog_debug("GameEventClass::Execute() - Executing '%s' event (GameFrame:%d, EventFrame:%d, HouseID:%d).", - Name_From(m_Type), - g_GameFrame, - m_EventFrame, - m_HouseID); + BOOL formation_event = false; + char message[100] = { '\0' }; + char *messageptr = nullptr; + // EVENT_DEBUG_LOG("GameEventClass::Execute() - Executing '%s' event (GameFrame:%d, EventFrame:%d, ID:%d).", + // Name_From(m_Type), + // g_GameFrame, + // m_EventFrame, + // m_HouseID); + FootClass *whom = nullptr; switch (m_Type) { - case EVENT_ALLY: + case EVENT_EMPTY: break; - case EVENT_MEGAMISSION: - EVENT_captainslog_debug(" MEGAMISSION - Whom:%08X, Mission:%s, Target:%08X, Dest:%08X.", - m_EventData.u_MegaMission.m_Whom, - MissionClass::Name_From(m_EventData.u_MegaMission.m_Mission), - m_EventData.u_MegaMission.m_Target, - m_EventData.u_MegaMission.m_Dest); + + // verified + case EVENT_ALLY: { + EVENT_DEBUG_LOG(" ALLY - House:%d.", m_EventData.u_House.m_Whom); + if (g_Houses[m_HouseID].Is_Ally((HousesType)m_EventData.u_House.m_Whom)) { + g_Houses[m_HouseID].Make_Enemy((HousesType)m_EventData.u_House.m_Whom); + } else { + g_Houses[m_HouseID].Make_Ally((HousesType)m_EventData.u_House.m_Whom); + } break; - case EVENT_MEGAMISSION_F: - EVENT_captainslog_debug( + } + + // verified + case EVENT_MEGAMISSION_F: { + EVENT_DEBUG_LOG( " MEGAMISSION_F - Whom:%08X, Mission:%s, Target:%08X\n" - " Dest:%08X, FormSpeed:%d, FormMaxSpeed:%d.\n", + " Dest:%08X, FormSpeed:%d, FormMaxSpeed:%d.", m_EventData.u_MegaMissionF.m_Whom, MissionClass::Name_From(m_EventData.u_MegaMissionF.m_Mission), m_EventData.u_MegaMissionF.m_Target, m_EventData.u_MegaMissionF.m_Dest, m_EventData.u_MegaMissionF.m_FormSpeed, m_EventData.u_MegaMissionF.m_FormMaxSpeed); + whom = (FootClass *)m_EventData.u_MegaMissionF.m_Whom.As_Techno(); + if (whom != nullptr && whom->Is_Active() && whom->Is_Foot()) { + whom->Set_In_Formation(true); + whom->Set_Team_Speed(m_EventData.u_MegaMissionF.m_FormSpeed); + whom->Set_Team_Max_Speed(m_EventData.u_MegaMissionF.m_FormMaxSpeed); + g_FormMove = true; + g_FormSpeed = m_EventData.u_MegaMissionF.m_FormSpeed; + g_FormMaxSpeed = m_EventData.u_MegaMissionF.m_FormMaxSpeed; + formation_event = true; + } + // fallthough + } + + case EVENT_MEGAMISSION: { + EVENT_DEBUG_LOG(" MEGAMISSION - Whom:%08X, Mission:%s, Target:%08X, Dest:%08X.", + m_EventData.u_MegaMission.m_Whom, + MissionClass::Name_From(m_EventData.u_MegaMission.m_Mission), + m_EventData.u_MegaMission.m_Target, + m_EventData.u_MegaMission.m_Dest); + FootClass *whom = (FootClass *)m_EventData.u_MegaMission.m_Whom.As_Techno(); + + if (whom != nullptr) { + if (whom->Is_Active() && whom->Get_Health() > 0 && !whom->In_Limbo()) { + ObjectClass *target = nullptr; + + if (m_EventData.u_MegaMission.m_Target.Valid_RTTI()) { + target = m_EventData.u_MegaMission.m_Target.As_Object(); + if (target != nullptr) { + if (!target->Is_Active() || !target->Get_Health() || target->In_Limbo()) { + break; + } + } + } + if (m_EventData.u_MegaMission.m_Dest.Valid_RTTI()) { + target = m_EventData.u_MegaMission.m_Dest.As_Object(); + if (target != nullptr) { + if (!target->Is_Active() || !target->Get_Health() || target->In_Limbo()) { + break; + } + } + } + + if (!whom->Is_Tethered()) { + whom->Transmit_Message(RADIO_OVER_AND_OUT); + } + + if (whom->Is_Foot()) { + if (formation_event == false) { + whom->Set_In_Formation(false); + } + + if (whom->Get_Team() != nullptr) { + whom->Get_Team()->Remove(whom, -1); + } + } + if (target != nullptr) { + if (g_PlayerPtr->Is_Ally(whom)) { + target->Clicked_As_Target(7); + } + } + + whom->Assign_Mission(m_EventData.u_MegaMission.m_Mission); + if (whom->Is_Foot()) { + whom->Set_Suspended_NavCom(0); + } + whom->Set_Suspended_TarCom(0); + + if (m_EventData.u_MegaMission.m_Mission == MISSION_AREA_GUARD && whom->Is_Foot()) { + whom->Assign_Target(0); + whom->Assign_Destination(m_EventData.u_MegaMission.m_Target); + whom->Set_Archive(m_EventData.u_MegaMission.m_Target); + + } else if (m_EventData.u_MegaMission.m_Mission == MISSION_QMOVE && whom->Is_Foot()) { + whom->Queue_Navigation_List(m_EventData.u_MegaMission.m_Dest); + + } else { + if (whom->Is_Foot()) { + whom->Clear_Navigation_List(); + } + whom->Assign_Target(m_EventData.u_MegaMission.m_Target); + whom->Assign_Destination(m_EventData.u_MegaMission.m_Dest); + } + + if (m_EventData.u_MegaMission.m_Mission == MISSION_MOVE) { + // TODO add code here to check for player and allies, + // as it stands this seems like it allows repairing at any shipyard, be it yours or enemy's + if (whom->What_Am_I() == RTTI_VESSEL) { + VesselClass *whomv = reinterpret_cast(whom); + BuildingClass *targetb = reinterpret_cast(target); + if (targetb != nullptr && targetb->What_Am_I() == RTTI_BUILDING + && (targetb->What_Type() == BUILDING_SYRD || targetb->What_Type() == BUILDING_SPEN)) { + whomv->Set_Self_Repair(true); + } else { + whomv->Set_Self_Repair(false); + whomv->Set_Repairing(false); + } + } + } + } + } break; - case EVENT_IDLE: - EVENT_captainslog_debug(" IDLE."); + } + + // verified + case EVENT_IDLE: { + EVENT_DEBUG_LOG(" IDLE - Whom:%08X.", m_EventData.u_Whom.m_Whom); + whom = (FootClass *)m_EventData.u_Whom.m_Whom.As_Techno(); + if (whom != nullptr && whom->Is_Active() && !whom->In_Limbo() && !whom->Is_Tethered() + && whom->What_Am_I() != RTTI_BUILDING) { + whom->Transmit_Message(RADIO_OVER_AND_OUT); + whom->Assign_Destination(0); + whom->Assign_Target(0); + whom->Enter_Idle_Mode(); + if (whom->Is_Foot()) { + whom->Clear_Navigation_List(); + } + } break; - case EVENT_SCATTER: - EVENT_captainslog_debug(" SCATTER."); + } + + // verified + case EVENT_SCATTER: { + EVENT_DEBUG_LOG(" SCATTER - Whom:%08X.", m_EventData.u_Whom.m_Whom); + whom = (FootClass *)m_EventData.u_Whom.m_Whom.As_Techno(); + if (whom != nullptr && whom->Is_Foot() && whom->Is_Active() && !whom->In_Limbo() && !whom->Is_Tethered()) { + whom->Set_To_Scatter(true); + whom->Scatter(0, 1, 0); + } break; - case EVENT_DESTRUCT: - EVENT_captainslog_debug(" DESTRUCT."); + } + + // verified + case EVENT_DESTRUCT: { + EVENT_DEBUG_LOG(" DESTRUCT."); + g_Houses[m_HouseID].Flag_To_Die(); break; - case EVENT_DEPLOY: - EVENT_captainslog_debug(" DEPLOY."); + } + + // verified + // not handled by the game + case EVENT_DEPLOY: { + EVENT_DEBUG_LOG(" DEPLOY."); break; - case EVENT_PLACE: - EVENT_captainslog_debug(" PLACE."); + } + + // verified + case EVENT_PLACE: { + EVENT_DEBUG_LOG(" PLACE - RTTI:%d Cell: X:%d Y:%d.", + m_EventData.u_RTTICell.m_RTTI, + Cell_Get_X(m_EventData.u_RTTICell.m_Cell), + Cell_Get_Y(m_EventData.u_RTTICell.m_Cell)); + g_Houses[m_HouseID].Place_Object(m_EventData.u_RTTICell.m_RTTI, m_EventData.u_RTTICell.m_Cell); break; - case EVENT_OPTIONS: - EVENT_captainslog_debug(" OPTIONS."); + } + + // verified + case EVENT_OPTIONS: { + EVENT_DEBUG_LOG(" OPTIONS."); + if (!g_Session.Playback_Game()) { + g_SpecialDialog = SPECIAL_DLG_OPTIONS; + } break; - case EVENT_GAMESPEED: - EVENT_captainslog_debug(" GAMESPEED - GameSpeed:%d.", m_EventData.u_GameSpeed.m_GameSpeed); + } + + // verified + case EVENT_GAMESPEED: { + EVENT_DEBUG_LOG(" GAMESPEED - GameSpeed:%d.", m_EventData.u_GameSpeed.m_GameSpeed); + g_Options.Set_Game_Speed(m_EventData.u_GameSpeed.m_GameSpeed); break; - case EVENT_PRODUCE: - EVENT_captainslog_debug(" PRODUCE."); + } + + // verified + case EVENT_PRODUCE: { + EVENT_DEBUG_LOG( + " PRODUCE - RTTI:%d HeapID:%d.", m_EventData.u_RTTIHeapID.m_RTTI, m_EventData.u_RTTIHeapID.m_HeapID); + g_Houses[m_HouseID].Begin_Production(m_EventData.u_RTTIHeapID.m_RTTI, m_EventData.u_RTTIHeapID.m_HeapID); break; - case EVENT_SUSPEND: - EVENT_captainslog_debug(" SUSPEND."); + } + + // verified + case EVENT_SUSPEND: { + EVENT_DEBUG_LOG(" SUSPEND - RTTI:%d.", m_EventData.u_RTTI.m_RTTI); + g_Houses[m_HouseID].Suspend_Production(m_EventData.u_RTTI.m_RTTI); break; - case EVENT_ABANDON: - EVENT_captainslog_debug(" ABANDON."); + } + + // verified + case EVENT_ABANDON: { + EVENT_DEBUG_LOG(" ABANDON - RTTI:%d.", m_EventData.u_RTTI.m_RTTI); + g_Houses[m_HouseID].Abandon_Production(m_EventData.u_RTTI.m_RTTI); break; - case EVENT_PRIMARY: - EVENT_captainslog_debug(" PRIMARY."); + } + + // verified + case EVENT_PRIMARY: { + EVENT_DEBUG_LOG(" PRIMARY - Whom:%08X.", m_EventData.u_Whom.m_Whom); + BuildingClass *whomb = (BuildingClass *)m_EventData.u_Whom.m_Whom.As_Building(); + if (whomb != nullptr && whomb->Is_Active()) { + whomb->Toggle_Primary(); + } break; - case EVENT_SPECIAL_PLACE: - EVENT_captainslog_debug(" SPECIAL_PLACE."); + } + + // verified + case EVENT_SPECIAL_PLACE: { + EVENT_DEBUG_LOG(" SPECIAL_PLACE - Special Weapon:%d Cell: X:%d Y:%d.", + m_EventData.u_SpecialPlace.m_SpecialWeapon, + Cell_Get_X(m_EventData.u_SpecialPlace.m_Cell), + Cell_Get_Y(m_EventData.u_SpecialPlace.m_Cell)); + g_Houses[m_HouseID].Place_Special_Blast( + (SpecialWeaponType)m_EventData.u_SpecialPlace.m_SpecialWeapon, m_EventData.u_SpecialPlace.m_Cell); break; - case EVENT_EXIT: - EVENT_captainslog_debug(" EXIT."); + } + + // verified + case EVENT_EXIT: { + EVENT_DEBUG_LOG(" EXIT."); + g_Theme.Fade_Out(); + Stop_Speaking(); + Speak(VOX_BATTLE_CONTROL_TERMINATED); + while (Is_Speaking()) { + Call_Back(); + } + g_GameActive = false; break; - case EVENT_ANIMATION: - EVENT_captainslog_debug(" ANIMATION - Anim:%s, Coord: X:%d Y:%d.", + } + + // verified + case EVENT_ANIMATION: { + EVENT_DEBUG_LOG(" ANIMATION - Anim:%s, Coord: X:%d Y:%d.", AnimTypeClass::Name_From(m_EventData.u_Anim.m_Anim), Coord_Lepton_X(m_EventData.u_Anim.m_Coord), Coord_Lepton_Y(m_EventData.u_Anim.m_Coord)); + AnimClass *aptr = new AnimClass(m_EventData.u_Anim.m_Anim, m_EventData.u_Anim.m_Coord, 0, 1); + if (aptr != nullptr && m_EventData.u_Anim.m_Owner != HOUSES_NONE) { + if (g_PlayerPtr->What_Type() != m_EventData.u_Anim.m_Owner) { + aptr->Make_Invisible(); + } + } break; - case EVENT_REPAIR: - EVENT_captainslog_debug(" REPAIR."); + } + + // verified + case EVENT_REPAIR: { + EVENT_DEBUG_LOG(" REPAIR - Whom:%08X.", m_EventData.u_Whom.m_Whom); + whom = (FootClass *)m_EventData.u_Whom.m_Whom.As_Techno(); + if (whom != nullptr && whom->Is_Active()) { + whom->Repair(); + } break; - case EVENT_SELL: - EVENT_captainslog_debug(" SELL."); + } + + // verified + case EVENT_SELL: { + EVENT_DEBUG_LOG(" SELL - Whom:%08X.", m_EventData.u_Whom.m_Whom); + whom = (FootClass *)m_EventData.u_Whom.m_Whom.As_Techno(); + if (whom != nullptr && whom->Is_Active()) { + if (&g_Houses[m_HouseID] == whom->Get_Owner_House()) { + if ((whom->What_Am_I() == RTTI_BUILDING || whom->What_Am_I() == RTTI_UNIT) + && g_Map[whom->Center_Cell()].Cell_Building() != nullptr) { + whom->Sell_Back(-1); + } + } + } break; - case EVENT_SELL_CELL: - EVENT_captainslog_debug(" SELL_CELL."); + } + + // verified + case EVENT_SELL_CELL: { + EVENT_DEBUG_LOG(" SELL_CELL - Cell: X:%d Y:%d.", + Cell_Get_X(m_EventData.u_Cell.m_Cell), + Cell_Get_Y(m_EventData.u_Cell.m_Cell)); + g_Houses[m_HouseID].Sell_Wall(m_EventData.u_Cell.m_Cell); break; - case EVENT_SPECIAL: - EVENT_captainslog_debug(" SPECIAL."); + } + + // verified + case EVENT_SPECIAL: { + EVENT_DEBUG_LOG(" SPECIAL."); + s_Special.Set(m_EventData.u_Special.m_Special); + sprintf(message, Text_String(TXT_SPECIAL_WARNING), g_Houses[m_HouseID].Get_Name()); + g_Session.Get_Messages().Add_Message( + nullptr, 0, message, g_Houses[m_HouseID].Get_Color(), TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_OUTLINE, 1200); + g_Map.Flag_To_Redraw(); break; - case EVENT_FRAME_SYNC: - EVENT_captainslog_debug(" FRAME_SYNC."); + } + + // verified + // not handled by the game + case EVENT_FRAME_SYNC: { + EVENT_DEBUG_LOG(" FRAME_SYNC."); break; - case EVENT_MESSAGE: - EVENT_captainslog_debug(" MESSAGE."); + } + + // verified + // not handled by the game + case EVENT_MESSAGE: { + EVENT_DEBUG_LOG(" MESSAGE."); break; - case EVENT_RESPONSE_TIME: - EVENT_captainslog_debug(" RESPONSE_TIME."); + } + + // verified + case EVENT_RESPONSE_TIME: { + EVENT_DEBUG_LOG( + " RESPONSE_TIME - Changing MaxAhead to frames %d.", m_EventData.u_ResponseTime.m_MaxAhead); + g_Session.Set_MaxAhead(m_EventData.u_ResponseTime.m_MaxAhead); break; - case EVENT_FRAME_INFO: - EVENT_captainslog_debug(" FRAME_INFO."); + } + + // verified + // not handled by the game + case EVENT_FRAME_INFO: { + EVENT_DEBUG_LOG(" FRAME_INFO."); break; - case EVENT_SAVE_GAME: - EVENT_captainslog_debug(" SAVE_GAME."); + } + + // verified + case EVENT_SAVE_GAME: { + EVENT_DEBUG_LOG(" SAVE_GAME."); + if (g_SpecialDialog != SPECIAL_DLG_NONE) { + Save_Game(-1, Text_String(TXT_MULTIPLAYER_GAME), 0); + } else { + TCountDownTimerClass timer(60); + MessageBoxClass msg; + msg.Process(TXT_SAVING_GAME); + Save_Game(-1, Text_String(TXT_MULTIPLAYER_GAME), 0); + while (timer.Time() > 0) { + Call_Back(); + } + g_HidPage.Clear(); + g_Map.Flag_To_Redraw(true); + g_Map.Render(); + } break; - case EVENT_ARCHIVE: - EVENT_captainslog_debug(" ARCHIVE - Whom:%08X, Target:%08X.", m_EventData.u_WhomTarget.m_Whom, m_EventData.u_WhomTarget.m_Target); + } + + // verified + // todo test with conyard deploy undeploy + case EVENT_ARCHIVE: { + EVENT_DEBUG_LOG( + " ARCHIVE - Whom:%08X, Target:%08X.", m_EventData.u_WhomTarget.m_Whom, m_EventData.u_WhomTarget.m_Target); + whom = (FootClass *)m_EventData.u_WhomTarget.m_Whom.As_Techno(); + if (whom != nullptr && whom->Is_Active()) { + whom->Set_Archive(m_EventData.u_WhomTarget.m_Target); + } break; - case EVENT_ADD_PLAYER: - EVENT_captainslog_debug(" ADD_PLAYER."); + } + + // verified + case EVENT_ADD_PLAYER: { + EVENT_DEBUG_LOG(" ADD_PLAYER."); + int *ptr = m_EventData.u_AddPlayer.m_pointer; + // BUGFIX, original assumed the pointer is always valid + if (ptr == nullptr) { + captainslog_debug("EVENT_ADD_PLAYER got a invalid pointer!"); + break; + } + + for (int i = 0; i < m_EventData.u_AddPlayer.m_uintval; ++i) { + EVENT_DEBUG_LOG("%d\n", ptr[i]); + } + + if (m_HouseID != g_PlayerPtr->Get_Heap_ID()) { + delete m_EventData.u_AddPlayer.m_pointer; + } break; - case EVENT_TIMING: - EVENT_captainslog_debug(" TIMING."); + } + + // verified + case EVENT_TIMING: { + EVENT_DEBUG_LOG(" TIMING - DesiredFrameRate:%d MaxAhead:%d.", + m_EventData.u_Timing.m_DesiredFrameRate, + m_EventData.u_Timing.m_MaxAhead); + if (m_EventData.u_Timing.m_MaxAhead < g_Session.Get_MaxAhead()) { + g_NewMaxAheadFrame1 = m_EventData.u_Timing.m_DesiredFrameRate; + g_NewMaxAheadFrame2 = m_EventData.u_Timing.m_MaxAhead + g_NewMaxAheadFrame1; + } + g_Session.Set_Desired_Frame_Rate(m_EventData.u_Timing.m_DesiredFrameRate); + g_Session.Set_MaxAhead(m_EventData.u_Timing.m_MaxAhead); break; - case EVENT_PROCESS_TIME: - EVENT_captainslog_debug(" PROCESS_TIME."); + } + + case EVENT_PROCESS_TIME: { + EVENT_DEBUG_LOG(" PROCESS_TIME - %04x ticks.", m_EventData.u_ProcessTime.m_Ticks); + for (int i = 0; i < g_Session.Player_Count(); ++i) { + NodeNameTag *nodename = g_Session.Player(i); + + if (nodename == nullptr) { + captainslog_debug("EVENT_PROCESS_TIME got a invalid pointer! This should never happen!"); + break; + } + + if (m_HouseID == nodename->m_AltHouse) { + nodename->field_19 = m_EventData.u_ProcessTime.m_Ticks; + break; + } + } break; - case EVENT_PROPOSE_DRAW: - EVENT_captainslog_debug(" PROPOSE_DRAW."); + } + + case EVENT_PROPOSE_DRAW: { + EVENT_DEBUG_LOG(" PROPOSE_DRAW."); + if (m_HouseID != g_PlayerPtr->Get_Heap_ID()) { + if (g_Scen.Get_field_7CF()) { + g_Scen.Set_field_7D3(true); + break; + } + for (int i = 0; i < g_Session.Player_Count(); ++i) { + if (m_HouseID == g_Session.Player(i)->m_AltHouse) { + g_Scen.Set_field_7D3(true); + sprintf(message, "%s has proposed that the game be declared a draw.", g_Session.Player(i)->m_Name); + messageptr = message; + break; + } + } + } else { + if (g_Scen.Get_field_7D3()) { + g_Scen.Set_field_7CF(true); + break; + } + g_Scen.Set_field_7CF(true); + messageptr = "You have proposed that the game be declared a draw."; + } + g_Session.Get_Messages().Add_Message(0, + 0, + messageptr, + PLAYER_COLOR_YELLOW, + TPF_6PT_GRAD | TPF_OUTLINE | TPF_USE_GRAD_PAL, + 900 * g_Rule.Message_Delay()); + Sound_Effect(VOC_INCOMING_MESSAGE); break; - case EVENT_RETRACT_DRAW: - EVENT_captainslog_debug(" RETRACT_DRAW."); + } + + case EVENT_RETRACT_DRAW: { + EVENT_DEBUG_LOG(" RETRACT_DRAW."); + + if (m_HouseID == g_PlayerPtr->Get_Heap_ID()) { + g_Scen.Set_field_7CF(false); + messageptr = "You have retracted your offer of a draw."; + } else { + for (int i = 0; i < g_Session.Player_Count(); ++i) { + if (m_HouseID == g_Session.Player(i)->m_AltHouse) { + sprintf(message, "%s has retracted the offer of a draw.", g_Session.Player(i)->m_Name); + break; + } + } + g_Scen.Set_field_7D3(false); + messageptr = message; + } + g_Session.Get_Messages().Add_Message(0, + 0, + messageptr, + PLAYER_COLOR_YELLOW, + TPF_6PT_GRAD | TPF_OUTLINE | TPF_USE_GRAD_PAL, + 900 * g_Rule.Message_Delay()); + Sound_Effect(VOC_INCOMING_MESSAGE); break; + } default: break; - }; - -#ifdef GAME_DLL - void (*func)(GameEventClass *) = reinterpret_cast(0x004BD0C8); - func(this); -#else -#endif + } + EVENT_DEBUG_LOG("\n"); + // EVENT_DEBUG_LOG("EventClass::Execute - Complete\n"); } char const *GameEventClass::Name_From(GameEventClass::GameEventType type) @@ -486,7 +812,7 @@ char const *GameEventClass::Name_From(GameEventClass::GameEventType type) captainslog_assert(type < EVENT_COUNT); if (type != EVENT_EMPTY && type < EVENT_COUNT) { - return s_EventTypeList[type].Name; + return EventTypeList[type].Name; } return ""; diff --git a/src/game/engine/gameevent.h b/src/game/engine/gameevent.h index 4727b83e..48af3ace 100644 --- a/src/game/engine/gameevent.h +++ b/src/game/engine/gameevent.h @@ -3,6 +3,7 @@ * * @author CCHyper * @author OmniBlade + * @author tomsons26 * * @brief * @@ -84,11 +85,11 @@ class GameEventClass GameEventClass(GameEventType type, RTTIType rtti, unsigned int heap_id); // For events: PLACE, PRODUCE GameEventClass(GameEventType type, RTTIType rtti, cell_t cell); // For events: GameEventClass(GameEventType type, SpecialWeaponType special, cell_t cell); // For events: SPECIAL_PLACE - GameEventClass(GameEventType type, void *a2, unsigned long a3); // For events: + GameEventClass(GameEventType type, void *a2, unsigned long a3); // For events: ADDPLAYER GameEventClass(GameEventType type, TargetClass whom); // For events: PRIMARY, SELL, IDLE, SCATTER, REPAIR GameEventClass(GameEventType type, TargetClass whom, TargetClass target); // For events: ARCHIVE GameEventClass(GameEventType type, AnimType anim, HousesType owner, coord_t coord); // For events: ANIMATION - GameEventClass(GameEventType type, unsigned int crc, unsigned short cmd_count, unsigned char delay); // For events: FRAME_SYNC + GameEventClass(GameEventType type, unsigned int crc, unsigned short cmd_count, unsigned char delay); // For events: FRAMEINFO GameEventClass(GameEventType type, unsigned short desired_frame_rate, unsigned short max_ahead); // For events: TIMING // TODO: Once GameEventClass is complete, and code for event below is under control, move @@ -114,47 +115,46 @@ class GameEventClass const char *Name() const { return Name_From(m_Type); } private: + // confirmed - MEGAMISSION struct MegaMissionEventStruct { - target_t m_Whom; + xTargetClass m_Whom; MissionType m_Mission; - target_t m_Target; - target_t m_Dest; + xTargetClass m_Target; + xTargetClass m_Dest; }; + // confirmed - MEGAMISSION_F struct MegaMissionFEventStruct { - target_t m_Whom; + xTargetClass m_Whom; MissionType m_Mission; - target_t m_Target; - target_t m_Dest; + xTargetClass m_Target; + xTargetClass m_Dest; SpeedType m_FormSpeed; MPHType m_FormMaxSpeed; }; + // confirmed - PRIMARY, SELL, IDLE, SCATTER, REPAIR struct WhomEventStruct { - target_t m_Whom; + xTargetClass m_Whom; }; + // confirmed - ARCHIVE struct WhomTargetEventStruct { - target_t m_Whom; - target_t m_Target; - }; - - struct WhomTargetDestEventStruct - { - target_t m_Whom; - target_t m_Target; - target_t m_Dest; + xTargetClass m_Whom; + xTargetClass m_Target; }; + // confirmed - ALLY struct HouseEventStruct { int /*HousesType*/ m_Whom; }; + // confirmed - ANIMATION struct AnimEventStruct { AnimType m_Anim; @@ -162,40 +162,47 @@ class GameEventClass coord_t m_Coord; }; + // confirmed - SELLCELL struct CellEventStruct { cell_t m_Cell; }; + // confirmed - SUSPEND, ABANDON struct RTTIEventStruct { RTTIType m_RTTI; }; + // confirmed - PLACE struct RTTICellEventStruct { RTTIType m_RTTI; cell_t m_Cell; }; + // confirmed - PRODUCE struct RTTIHeapIDEventStruct { RTTIType m_RTTI; int m_HeapID; }; + // confirmed - SPECIAL_PLACE struct SpecialPlaceEventStruct { - int /*SpecialWeaponType*/ m_Special; + int /*SpecialWeaponType*/ m_SpecialWeapon; cell_t m_Cell; }; + // confirmed - SPECIAL struct SpecialEventStruct { void operator=(const SpecialClass &that) { m_Special = that.Pack(); } uint32_t m_Special; }; + // confirmed - FRAMEINFO struct FrameEventStruct { unsigned int m_CRC; @@ -203,24 +210,40 @@ class GameEventClass unsigned char m_Delay; }; + // confirmed - TIMING struct TimingEventStruct { - unsigned int m_DesiredFrameRate : 16; // 1 - unsigned int m_MaxAhead : 16; // 16 + unsigned short m_DesiredFrameRate; + unsigned short m_MaxAhead; }; - struct TimeEventStruct + // confirmed - RESPONSE_TIME + struct ResponseTimeEventStruct { unsigned char m_MaxAhead; }; + // confirmed - GAMESPEED struct GameSpeedEventStruct { unsigned int m_GameSpeed; }; + // confirmed - ADDPLAYER + struct AddPlayerEventStruct + { + int *m_pointer; + unsigned int m_uintval; + }; + + // confirmed - PROCESS_TIME + struct ProcessTimeEventStruct + { + unsigned short m_Ticks; + }; + private: - GameEventType m_Type; // The type for this object. + GameEventType m_Type; // The type for this object (def = EVENT_NONE). #ifndef CHRONOSHIFT_NO_BITFIELDS unsigned int m_EventFrame : 26; // @@ -249,10 +272,14 @@ class GameEventClass SpecialEventStruct u_Special; FrameEventStruct u_Frame; TimingEventStruct u_Timing; - TimeEventStruct u_ResponseTime; + ResponseTimeEventStruct u_ResponseTime; GameSpeedEventStruct u_GameSpeed; + AddPlayerEventStruct u_AddPlayer; + ProcessTimeEventStruct u_ProcessTime; } m_EventData; +public: + public: struct EventInfoStruct { @@ -260,7 +287,7 @@ class GameEventClass int RawSize; }; - static EventInfoStruct s_EventTypeList[EVENT_COUNT]; + static EventInfoStruct EventTypeList[EVENT_COUNT]; static char const *Name_From(GameEventType type); static GameEventType From_Name(char const *name); }; diff --git a/src/game/engine/gameloop.cpp b/src/game/engine/gameloop.cpp index 59270385..db984b18 100644 --- a/src/game/engine/gameloop.cpp +++ b/src/game/engine/gameloop.cpp @@ -254,7 +254,7 @@ BOOL Main_Loop() g_FrameTimer = 60 / g_Session.Desired_Frame_Rate(); } } else { - int game_speed = g_Options.Game_Speed(); + int game_speed = g_Options.Get_Game_Speed(); DiffType ai_diff = g_PlayerPtr->Get_AI_Difficulty(); if (game_speed > 0) { g_FrameTimer = game_speed + ((ai_diff == DIFF_EASIEST) - (ai_diff == DIFF_NORMAL)); diff --git a/src/game/engine/house.h b/src/game/engine/house.h index d540d328..588ac17e 100644 --- a/src/game/engine/house.h +++ b/src/game/engine/house.h @@ -215,6 +215,7 @@ class HouseClass RTTIType What_Am_I() const { return m_RTTI; } int Get_Heap_ID() const { return m_HeapID; } + PlayerColorType Get_Color() const { return m_Color; } HousesType What_Type() const { return m_Class->What_Type(); } const char *Get_Name() const { return m_Class->Get_Name(); } diff --git a/src/game/engine/options.h b/src/game/engine/options.h index 1113a5a4..d312931e 100644 --- a/src/game/engine/options.h +++ b/src/game/engine/options.h @@ -71,8 +71,9 @@ class OptionsClass void Set_Contrast(fixed_t contrast); void Set_Tint(fixed_t tint); void Set(); + void Set_Game_Speed(int speed) { m_GameSpeed = speed; } - int Game_Speed() const { return m_GameSpeed; } + int Get_Game_Speed() const { return m_GameSpeed; } int Get_Scroll_Rate() const { return m_ScrollRate; } const fixed_t &Get_Sound_Volume() const { return m_Volume; } const fixed_t &Get_Score_Volume() const { return m_ScoreVolume; } diff --git a/src/game/engine/saveload.cpp b/src/game/engine/saveload.cpp index dbf79371..da3ae684 100644 --- a/src/game/engine/saveload.cpp +++ b/src/game/engine/saveload.cpp @@ -33,10 +33,10 @@ void Put_All(Pipe &pipe, int skip_callback) #endif } -int Save_Game(int number, char *savename, int unknown) +BOOL Save_Game(int number, const char *savename, BOOL unknown) { -#ifdef GAME_DLL - int (*func)(int, char *, int) = reinterpret_cast(0x005379FC); +#ifndef CHRONOSHIFT_STANDALONE + BOOL (*func)(int, const char *, BOOL) = reinterpret_cast(0x005379FC); return func(number, savename, unknown); #else return 0; @@ -52,11 +52,11 @@ void Post_Load_Game(int skip_overpass) g_Map.Zone_Reset(15); } -int Load_Game(int unknown) +BOOL Load_Game(int number) { -#ifdef GAME_DLL - int (*func)() = reinterpret_cast(0x00537D10); - return func(); +#ifndef CHRONOSHIFT_STANDALONE + BOOL (*func)(int) = reinterpret_cast(0x00537D10); + return func(number); #else return 0; #endif diff --git a/src/game/engine/saveload.h b/src/game/engine/saveload.h index 25bd674d..2eb55472 100644 --- a/src/game/engine/saveload.h +++ b/src/game/engine/saveload.h @@ -38,8 +38,8 @@ enum }; void Put_All(Pipe &pipe, int skip_callback); -int Save_Game(int number, char *savename, int unknown); -int Load_Game(int unknown); +BOOL Save_Game(int number, const char *savename, BOOL unknown); +BOOL Load_Game(int number); int Save_Misc_Values(Pipe &pipe); int Load_Misc_Values(Straw &straw); int Save_MPlayer_Values(Pipe &pipe); diff --git a/src/game/engine/scenario.h b/src/game/engine/scenario.h index 78099924..b8badbf8 100644 --- a/src/game/engine/scenario.h +++ b/src/game/engine/scenario.h @@ -100,7 +100,9 @@ class ScenarioClass void Set_Bridge_Count(int count) { m_BridgeCount = count; } BOOL Get_Global(int index) const { return m_GlobalVariables[index]; } BOOL Get_field_7CF() const { return m_field_7CF; } + void Set_field_7CF(int state) { m_field_7CF = state; } BOOL Get_field_7D3() const { return m_field_7D3; } + void Set_field_7D3(int state) { m_field_7D3 = state; } BOOL Evacuate_Civilians() const { return m_CivEvac; } #ifdef GAME_DLL diff --git a/src/game/engine/session.h b/src/game/engine/session.h index 6290ac15..28eeeefb 100644 --- a/src/game/engine/session.h +++ b/src/game/engine/session.h @@ -99,6 +99,7 @@ struct NodeNameTag HousesType m_House; PlayerColorType m_Color; HousesType m_AltHouse; + int field_19; //set in PROCESS_TIME event }; class SessionClass @@ -112,6 +113,8 @@ class SessionClass GameEnum Game_To_Play() const { return m_GameToPlay; } void Set_Game_To_Play(GameEnum game) { m_GameToPlay = game; } + void Set_MaxAhead(int maxahead) { m_MaxAhead = maxahead; } + int Get_MaxAhead() { return m_MaxAhead; } CommProtocolEnum Packet_Protocol() const { return m_PacketProtocol; } int Frame_Send_Rate() { return m_FrameSendRate; } @@ -169,6 +172,8 @@ class SessionClass DynamicVectorClass &Games_List() { return m_Games; } DynamicVectorClass &Players_List() { return m_Players; } DynamicVectorClass &Network_Players_List() { return m_NetworkPlayers; } + int Player_Count() const { return m_Players.Count(); } + NodeNameTag *Player(int num) { return m_Players[num]; } BOOL Modem_Service() const { return m_ModemService; } diff --git a/src/game/engine/special.h b/src/game/engine/special.h index 1e53bb58..aef2c293 100644 --- a/src/game/engine/special.h +++ b/src/game/engine/special.h @@ -46,6 +46,7 @@ class SpecialClass BOOL Always_Show_Health() { return m_ShowHealth; } uint32_t Pack() const { return m_SpecialFlags; } + void Set(uint32_t special) { m_SpecialFlags = special; } private: union diff --git a/src/game/engine/target.cpp b/src/game/engine/target.cpp index cc97ba3e..bcfd6cf2 100644 --- a/src/game/engine/target.cpp +++ b/src/game/engine/target.cpp @@ -16,15 +16,27 @@ #include "target.h" #include "cell.h" #include "coord.h" +#include "iomap.h" #include "object.h" #include "techno.h" #include "technotype.h" -//#include "triggertype.h" +#include "triggertype.h" +#include "aircraft.h" +#include "anim.h" +#include "building.h" +#include "bullet.h" +#include "infantry.h" +#include "overlay.h" +#include "smudge.h" +#include "terrain.h" +#include "unit.h" +#include "vessel.h" + CellClass *TargetClass::As_Cell() const { return nullptr; - //return ::As_Cell(m_Target); + // return ::As_Cell(m_Target); } AbstractClass *TargetClass::As_Abstract() const @@ -35,7 +47,7 @@ AbstractClass *TargetClass::As_Abstract() const AbstractTypeClass *TargetClass::As_TypeClass() const { return nullptr; - //return ::As_TypeClass(m_Target); + // return ::As_TypeClass(m_Target); } TechnoClass *TargetClass::As_Techno() const @@ -50,7 +62,7 @@ ObjectClass *TargetClass::As_Object() const TargetClass::TargetClass(AbstractClass *abstract) { - if (abstract != nullptr){ + if (abstract != nullptr) { m_Target = (abstract->What_Am_I() << 24) | (abstract->Get_Heap_ID() & 0xFFFFFF); } else { m_RTTI = RTTI_NONE; @@ -59,7 +71,7 @@ TargetClass::TargetClass(AbstractClass *abstract) TargetClass::TargetClass(AbstractTypeClass *abstractype) { - if (abstractype != nullptr){ + if (abstractype != nullptr) { m_Target = (abstractype->What_Am_I() << 24) | (abstractype->Get_Heap_ID() & 0xFFFFFF); } else { m_RTTI = RTTI_NONE; @@ -68,7 +80,7 @@ TargetClass::TargetClass(AbstractTypeClass *abstractype) TargetClass::TargetClass(CellClass *cell) { - if (cell != nullptr){ + if (cell != nullptr) { m_Target = (RTTI_CELL << 24) | (cell->Cell_Number() & 0xFFFFFF); } else { m_RTTI = RTTI_NONE; @@ -80,6 +92,141 @@ TargetClass::TargetClass(cell_t cellnum) m_Target = (RTTI_CELL << 24) | (cellnum & 0xFFFFFF); } +CellClass *xTargetClass::As_Cell() const +{ + if (Get_RTTI() == RTTI_CELL) { + return &g_Map[Get_ID()]; + } + + return nullptr; +} + +AbstractClass *xTargetClass::As_Abstract() const +{ + const int id = Get_ID(); + switch (Get_RTTI()) { + case RTTI_TEAM: + return &g_Teams[id]; + case RTTI_BULLET: + return &g_Bullets[id]; + case RTTI_OVERLAY: + return &g_Overlays[id]; + case RTTI_SMUDGE: + return &g_Smudges[id]; + case RTTI_UNIT: + return &g_Units[id]; + case RTTI_VESSEL: + return &g_Vessels[id]; + case RTTI_BUILDING: + return &g_Buildings[id]; + case RTTI_INFANTRY: + return &g_Infantry[id]; + case RTTI_AIRCRAFT: + return &g_Aircraft[id]; + case RTTI_TERRAIN: + return &g_Terrains[id]; + case RTTI_ANIM: + return &g_Anims[id]; + default: + break; + } + return nullptr; +} + +AbstractTypeClass *xTargetClass::As_TypeClass() const +{ + const int id = Get_ID(); + switch (Get_RTTI()) { + // TODO, look into this, i don't think the RTTI checks not checking TYPE are correct..... + case RTTI_TEAMTYPE: + return TeamTypeClass::As_Pointer((TeamType)id); + case RTTI_TRIGGERTYPE: + return TriggerTypeClass::As_Pointer((TriggerType)id); + case RTTI_BULLETTYPE: + return BulletTypeClass::As_Pointer((BulletType)id); + case RTTI_OVERLAY: + return OverlayTypeClass::As_Pointer((OverlayType)id); + case RTTI_SMUDGE: + return SmudgeTypeClass::As_Pointer((SmudgeType)id); + case RTTI_UNIT: + return UnitTypeClass::As_Pointer((UnitType)id); + case RTTI_VESSEL: + return VesselTypeClass::As_Pointer((VesselType)id); + case RTTI_BUILDING: + return BuildingTypeClass::As_Pointer((BuildingType)id); + case RTTI_INFANTRY: + return InfantryTypeClass::As_Pointer((InfantryType)id); + case RTTI_AIRCRAFT: + return AircraftTypeClass::As_Pointer((AircraftType)id); + case RTTI_TERRAIN: + return TerrainTypeClass::As_Pointer((TerrainType)id); + case RTTI_ANIM: + return AnimTypeClass::As_Pointer((AnimType)id); + default: + break; + } + return nullptr; +} + +TechnoClass *xTargetClass::As_Techno() const +{ + const int id = Get_ID(); + switch (Get_RTTI()) { + case RTTI_UNIT: + return &g_Units[id]; + case RTTI_VESSEL: + return &g_Vessels[id]; + case RTTI_BUILDING: + return &g_Buildings[id]; + case RTTI_INFANTRY: + return &g_Infantry[id]; + case RTTI_AIRCRAFT: + return &g_Aircraft[id]; + default: + break; + } + return nullptr; +} + +ObjectClass *xTargetClass::As_Object() const +{ + const int id = Get_ID(); + switch (Get_RTTI()) { + case RTTI_TERRAIN: + return &g_Terrains[id]; + case RTTI_SMUDGE: + return &g_Smudges[id]; + case RTTI_OVERLAY: + return &g_Overlays[id]; + case RTTI_BULLET: + return &g_Bullets[id]; + case RTTI_ANIM: + return &g_Anims[id]; + case RTTI_UNIT: + return &g_Units[id]; + case RTTI_VESSEL: + return &g_Vessels[id]; + case RTTI_BUILDING: + return &g_Buildings[id]; + case RTTI_INFANTRY: + return &g_Infantry[id]; + case RTTI_AIRCRAFT: + return &g_Aircraft[id]; + default: + break; + } + return nullptr; +} + +BuildingClass *xTargetClass::As_Building() const +{ + if (Get_RTTI() == RTTI_BUILDING) { + return (BuildingClass *)As_Techno(); + } + + return nullptr; +} + BOOL Target_Is_Techno(target_t target) { TechnoClass *ptr = As_Techno(target); @@ -168,6 +315,12 @@ AbstractClass *As_Abstract(target_t target) return (AbstractClass *)As_Object(target); } +// FIXME +AbstractTypeClass *As_TypeClass(target_t target) +{ + return nullptr; +} + ObjectClass *As_Object(target_t target) { #ifdef GAME_DLL @@ -355,7 +508,7 @@ coord_t As_Coord(target_t target) #else if (!Target_Legal(target)) { return 0; -} + } if (!Target_Is_Cell(target)) { ObjectClass *objptr = As_Object(target); return (objptr != nullptr ? objptr->Target_Coord() : 0); @@ -369,7 +522,7 @@ coord_t As_Coord(target_t target) coord_t As_Movement_Coord(target_t target) { #ifdef GAME_DLL - coord_t(*func)(target_t) = reinterpret_cast(0x005553F8); + coord_t (*func)(target_t) = reinterpret_cast(0x005553F8); return func(target); #else if (!Target_Legal(target)) { diff --git a/src/game/engine/target.h b/src/game/engine/target.h index 790d97b1..c7458a1e 100644 --- a/src/game/engine/target.h +++ b/src/game/engine/target.h @@ -69,6 +69,40 @@ class TargetClass }; }; +// this class is for use with EventClass, as unions can't have constructors +class xTargetClass +{ +public: + CellClass *As_Cell() const; + AbstractClass *As_Abstract() const; + AbstractTypeClass *As_TypeClass() const; + TechnoClass *As_Techno() const; + ObjectClass *As_Object() const; + BuildingClass *As_Building() const; + + void operator=(TargetClass &target) { m_Target = target; } + + bool Valid_RTTI() const + { + return Get_RTTI() != RTTI_NONE; + } + + RTTIType Get_RTTI() const + { + return RTTIType((m_Target & 0xFF000000) >> 24); + } + + int Get_ID() const + { + return m_Target & 0xFFFFFF; + } + + operator target_t() { return m_Target; } + +private: + target_t m_Target; +}; + inline target_t Make_Target(RTTIType type, int id) { return ((type & 0xFF) << 24) | (id & 0xFFFFFF); @@ -79,6 +113,11 @@ inline RTTIType Target_Get_RTTI(target_t target) return RTTIType((target & 0xFF000000) >> 24); } +inline bool Target_Valid_RTTI(target_t target) +{ + return ((target & 0xFF000000) >> 24) != RTTI_NONE; +} + inline int Target_Get_ID(target_t target) { return (target & 0xFFFFFF); @@ -134,6 +173,7 @@ TeamClass *As_Team(target_t target); TeamTypeClass *As_TeamType(target_t target); AbstractClass *As_Abstract(target_t target); ObjectClass *As_Object(target_t target); +AbstractTypeClass *As_TypeClass(target_t target); AnimClass *As_Animation(target_t target); BulletClass *As_Bullet(target_t target); TerrainClass *As_Terrain(target_t target); diff --git a/src/game/engine/teamtype.cpp b/src/game/engine/teamtype.cpp index 0b98d1f0..e8255f49 100644 --- a/src/game/engine/teamtype.cpp +++ b/src/game/engine/teamtype.cpp @@ -437,6 +437,14 @@ TeamTypeClass *TeamTypeClass::As_Pointer(const char *name) return From_Name(name); } +/** + * Gets a TriggerTypeClass pointer from its heap ID. + */ +TeamTypeClass *TeamTypeClass::As_Pointer(TeamType type) +{ + return type != TEAMTYPE_NONE && type < g_TeamTypes.Count() ? &g_TeamTypes[type] : nullptr; +} + /** * Get a pointer to a team type from its name. */ diff --git a/src/game/engine/teamtype.h b/src/game/engine/teamtype.h index 499d325b..ea9dd495 100644 --- a/src/game/engine/teamtype.h +++ b/src/game/engine/teamtype.h @@ -32,6 +32,12 @@ class ObjectTypeClass; class TriggerTypeClass; class GameINIClass; +// This enum is just for casting the TeamType heap indexes. +enum TeamType +{ + TEAMTYPE_NONE = 0xFFFFFFFF, +}; + enum TeamMissionType { TMISSION_ATTACK, // "Attack..." @@ -121,6 +127,7 @@ class TeamTypeClass : public AbstractTypeClass static TeamMissionType Mission_From_Name(const char *name); static const char *Name_From_Mission(TeamMissionType tmission); static TeamTypeClass *As_Pointer(const char *name); + static TeamTypeClass *As_Pointer(TeamType type); static TeamTypeClass *From_Name(const char *name); static TeamTypeClass *Suggested_New_Team(HouseClass *house, int32_t avail_air, int32_t avail_unit, int32_t avail_inf, int32_t avail_vessel, BOOL allow_autocreate); diff --git a/src/game/engine/techno.h b/src/game/engine/techno.h index 7d0cd62b..7bf52d5e 100644 --- a/src/game/engine/techno.h +++ b/src/game/engine/techno.h @@ -175,6 +175,7 @@ class TechnoClass : public RadioClass int Get_Price() const { return m_Price; } void Set_Price(int price) { m_Price = price; } void Set_Archive(target_t archive) { m_Archive = archive; } + void Set_Suspended_TarCom(target_t target) { m_SuspendedTarCom = target; } target_t Get_TarCom() const { return m_TarCom; } BOOL Can_Teleport_Here(cell_t cell) const; diff --git a/src/game/engine/triggertype.h b/src/game/engine/triggertype.h index 48be724c..0e72f861 100644 --- a/src/game/engine/triggertype.h +++ b/src/game/engine/triggertype.h @@ -32,7 +32,7 @@ class TriggerClass; // This enum is just for casting the TriggerType heap indexes. enum TriggerType { - TRIGGER_NONE = -1, + TRIGGER_NONE = 0xFFFFFFFF, }; DEFINE_ENUMERATION_OPERATORS(TriggerType); diff --git a/src/game/engine/vessel.h b/src/game/engine/vessel.h index f5cd8841..8518558d 100644 --- a/src/game/engine/vessel.h +++ b/src/game/engine/vessel.h @@ -89,6 +89,9 @@ class VesselClass : public DriveClass VesselType What_Type() const { return m_Class->What_Type(); } + void Set_Self_Repair(BOOL state) { m_ToSelfRepair = state; } + void Set_Repairing(BOOL state) { m_Repairing = state; } + static void Init(); #ifdef GAME_DLL diff --git a/src/hooker/setuphooks.cpp b/src/hooker/setuphooks.cpp index e58a6498..5fcfada3 100644 --- a/src/hooker/setuphooks.cpp +++ b/src/hooker/setuphooks.cpp @@ -1147,6 +1147,9 @@ void Setup_Hooks() Hook_Function(0x00528C78, *Queue_Mission); Hook_Function(0x00528D18, *Queue_Mission_Formation); Hook_Function(0x0052BC94, *Clean_Scheduled_Events); + + // gameevent.cpp + Hook_Function(0x004BD0C8, *GameEventClass::Execute); #endif }