diff --git a/source/graphics/Unit.h b/source/graphics/Unit.h index 04da0203fa..bd1ee38849 100644 --- a/source/graphics/Unit.h +++ b/source/graphics/Unit.h @@ -65,6 +65,9 @@ public: // Get player ID of this unit int GetPlayerID() { return m_PlayerID; } + // Most units have a hopefully-unique ID number, so they can be referred to + // persistently despite saving/loading maps. Default for new units is -1; should + // usually be set to CUnitManager::GetNewID() after creation. int GetID() const { return m_ID; } void SetID(int id) { m_ID = id; } diff --git a/source/lib/debug.h b/source/lib/debug.h index 8b32dddb9c..f73edc34dc 100644 --- a/source/lib/debug.h +++ b/source/lib/debug.h @@ -365,7 +365,7 @@ STMT(\ #define debug_warn(expr) \ STMT(\ static u8 suppress__;\ - switch(debug_assert_failed(#expr, &suppress__, __FILE__, __LINE__, __func__))\ + switch(debug_assert_failed(expr, &suppress__, __FILE__, __LINE__, __func__))\ {\ case ER_BREAK:\ debug_break();\ diff --git a/source/lib/ogl.cpp b/source/lib/ogl.cpp index 2d7300a9d9..f3bb757287 100644 --- a/source/lib/ogl.cpp +++ b/source/lib/ogl.cpp @@ -240,6 +240,8 @@ static void importExtensionFunctions() // It should be safe to load the ARB function pointers even if the // extension isn't advertised, since we won't actually use them without // checking for the extension. + // (TODO: this calls oglHaveVersion far more times than is necessary - + // we should probably use the have_* variables instead) #define FUNC(ret, name, params) *(void**)&p##name = SDL_GL_GetProcAddress(#name); #define FUNC2(ret, nameARB, nameCore, version, params) \ p##nameARB = NULL; \ @@ -280,6 +282,7 @@ void oglCheck() // glGetError may return multiple errors, so we poll it in a loop. // the debug_warn should only happen once (if this is set), though. bool error_enountered = false; + GLenum first_error = 0; for(;;) { @@ -287,12 +290,19 @@ void oglCheck() if(err == GL_NO_ERROR) break; + if(!error_enountered) + first_error = err; + error_enountered = true; dump_gl_error(err); } if(error_enountered) - debug_warn("OpenGL error(s) occurred"); + { + char msg[64]; + snprintf(msg, ARRAY_SIZE(msg), "OpenGL error(s) occurred: %04x", (int)first_error); + debug_warn(msg); + } } #endif @@ -308,6 +318,7 @@ void oglSquelchError(GLenum err_to_ignore) // glGetError may return multiple errors, so we poll it in a loop. // the debug_warn should only happen once (if this is set), though. bool error_enountered = false; + GLenum first_error = 0; for(;;) { @@ -318,12 +329,19 @@ void oglSquelchError(GLenum err_to_ignore) if(err == err_to_ignore) continue; + if(!error_enountered) + first_error = err; + error_enountered = true; dump_gl_error(err); } if(error_enountered) - debug_warn("OpenGL error(s) occurred"); + { + char msg[64]; + snprintf(msg, ARRAY_SIZE(msg), "OpenGL error(s) occurred: %04x", (int)first_error); + debug_warn(msg); + } } diff --git a/source/ps/Encryption.cpp b/source/ps/Encryption.cpp deleted file mode 100644 index e701e79d67..0000000000 --- a/source/ps/Encryption.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// last modified Friday, May 09, 2003 - -#include "precompiled.h" - -#include "Encryption.h" - -//-------------------------------------------------------------------- -// EncryptData - Takes A pointer to data in memory, the length of that data, -// Along with a key in memory and its length. It will allocated space -// for the encrypted copy of the data via new[], It is the responsiblity of the user -// to call delete[]. -//-------------------------------------------------------------------- -char *EncryptData(char *Data, long DataLength, char *Key, long KeyLength) -{ - // Allocate space for new Encrypted data - char *NewData = new char[DataLength]; - - // A counter to hold our absolute position in data - long DataOffset = 0; - - // Loop through Data until end is reached - while (DataOffset < DataLength) - { - // Loop through the key - for (long KeyOffset = 0; KeyOffset < KeyLength; KeyOffset++) - { - // If were at end of data break and the the while loop should end as well. - if (DataOffset >= DataLength) - break; - - // Otherwise Add the previous element of the key from the newdata - // (just something a little extra to confuse the hackers) - if (KeyOffset > 0) // Don't mess with the first byte - NewData[DataOffset] += Key[KeyOffset - 1]; - - // Xor the Data byte with the key byte and get new data - NewData[DataOffset] = Data[DataOffset] ^ Key[KeyOffset]; - - // Increase position in data - DataOffset++; - } - } - - // return the new data - return NewData; -} - - -//-------------------------------------------------------------------- -// DecryptData - Takes A pointer to data in memory, the length of that data, -// Along with a key in memory and its length. It will allocated space -// for the decrypted copy of the data via new[], It is the responsiblity of the user -// to call delete[]. -//-------------------------------------------------------------------- -char *DecryptData(char *Data, long DataLength, char *Key, long KeyLength) -{ - // Allocate space for new Decrypted data - char *NewData = new char[DataLength]; - - // A counter to hold our absolute position in data - long DataOffset = 0; - - // Loop through Data until end is reached - while (DataOffset < DataLength) - { - // Loop through the key - for (long KeyOffset = 0; KeyOffset < KeyLength; KeyOffset++) - { - // If were at end of data break and the the while loop should end as well. - if (DataOffset >= DataLength) - break; - - // Otherwise Xor the Data byte with the key byte and get new data - NewData[DataOffset] = Data[DataOffset] ^ Key[KeyOffset]; - - // Subtract the previous element of the key from the newdata - // (just something a little extra to confuse the hackers) - if (KeyOffset > 0) // Don't mess with the first byte - NewData[DataOffset] -= Key[KeyOffset - 1]; - - // Increase position in data - DataOffset++; - } - } - - // return the new data - return NewData; -} diff --git a/source/ps/Encryption.h b/source/ps/Encryption.h deleted file mode 100644 index 1f9e25b518..0000000000 --- a/source/ps/Encryption.h +++ /dev/null @@ -1,30 +0,0 @@ -/* -Encryption.h -by Caecus -caecus18@hotmail.com - -Two simple functions for encrypting and decrypting data. The KeyLength is -specified in bytes, therefore Keys must be in multiples of 8 bits. I'd -advice using 128bit keys which you can define as such. - -char MyKey[16] = { char(0xAF), char(0x2B), char(0x80), char(0x7E), - char(0x09), char(0x23), char(0xCC), char(0x95), - char(0xB4), char(0x2D), char(0xF4), char(0x90), - char(0xB3), char(0xC4), char(0x2A), char(0x3B) }; - -There may be a better way to do this but this looks alright to me. -*/ - - -#include "Pyrogenesis.h" - -#ifndef ENCRYPTION_H -#define ENCRYPTION_H - -// Simple Encryption function -char *EncryptData(char *Data, long DataLength, char *Key, long KeyLength); - -// Simple Decryption function -char *DecryptData(char *Data, long DataLength, char *Key, long KeyLength); - -#endif diff --git a/source/simulation/Entity.cpp b/source/simulation/Entity.cpp index 86f15cd695..012add7173 100644 --- a/source/simulation/Entity.cpp +++ b/source/simulation/Entity.cpp @@ -149,8 +149,11 @@ CEntity::~CEntity() void CEntity::loadBase() { + int previous_unit_id = -1; + if( m_actor ) { + previous_unit_id = m_actor->GetID(); g_Game->GetWorld()->GetUnitManager().RemoveUnit( m_actor ); delete( m_actor ); m_actor = NULL; @@ -164,6 +167,8 @@ void CEntity::loadBase() CStr actorName ( m_base->m_actorName ); // convert CStrW->CStr8 m_actor = g_Game->GetWorld()->GetUnitManager().CreateUnit( actorName, this, m_actorSelections ); + if( m_actor ) + m_actor->SetID( previous_unit_id ); // Set up our instance data diff --git a/source/simulation/EntityScriptInterface.cpp b/source/simulation/EntityScriptInterface.cpp index 35b24ed2b1..03ea5c0498 100644 --- a/source/simulation/EntityScriptInterface.cpp +++ b/source/simulation/EntityScriptInterface.cpp @@ -209,11 +209,8 @@ JSBool CEntity::Construct( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsva jsval CEntity::ToString( JSContext* cx, uintN UNUSED(argc), jsval* UNUSED(argv) ) { - wchar_t buffer[256]; - swprintf( buffer, 256, L"[object Entity: %ls]", m_base->m_Tag.c_str() ); - buffer[255] = 0; - utf16string str16(buffer, buffer+wcslen(buffer)); - return( STRING_TO_JSVAL( JS_NewUCStringCopyZ( cx, str16.c_str() ) ) ); + CStrW name( L"[object Entity: " + m_base->m_Tag + L"]" ); + return( STRING_TO_JSVAL( JS_NewUCStringCopyZ( cx, name.utf16().c_str() ) ) ); } jsval CEntity::JSI_GetPlayer() diff --git a/source/simulation/Simulation.cpp b/source/simulation/Simulation.cpp index 615d1ba310..03a608f876 100644 --- a/source/simulation/Simulation.cpp +++ b/source/simulation/Simulation.cpp @@ -247,8 +247,8 @@ uint CSimulation::TranslateMessage(CNetMessage* pMsg, uint clientMask, void* UNU CEntityOrder order; bool isQueued = true; -#define ENTITY_POSITION(_msg, _order) do\ - { \ +#define ENTITY_POSITION(_msg, _order) \ + do { \ _msg *msg=(_msg *)pMsg; \ isQueued = msg->m_IsQueued != 0; \ order.m_type=CEntityOrder::_order; \ @@ -256,8 +256,8 @@ uint CSimulation::TranslateMessage(CNetMessage* pMsg, uint clientMask, void* UNU order.m_target_location.y=(float)msg->m_TargetY; \ RandomizeLocations(order, msg->m_Entities, isQueued); \ } while(0) -#define ENTITY_POSITION_FORM(_msg, _order) do\ - { \ +#define ENTITY_POSITION_FORM(_msg, _order) \ + do { \ _msg *msg=(_msg *)pMsg; \ isQueued = msg->m_IsQueued != 0; \ order.m_type=CEntityOrder::_order; \ @@ -265,8 +265,8 @@ uint CSimulation::TranslateMessage(CNetMessage* pMsg, uint clientMask, void* UNU order.m_target_location.y=(float)msg->m_TargetY; \ FormationLocations(order, msg->m_Entities, isQueued); \ } while(0) -#define ENTITY_ENTITY_INT(_msg, _order) do\ - { \ +#define ENTITY_ENTITY_INT(_msg, _order) \ + do { \ _msg *msg=(_msg *)pMsg; \ isQueued = msg->m_IsQueued != 0; \ order.m_type=CEntityOrder::_order; \ @@ -274,8 +274,8 @@ uint CSimulation::TranslateMessage(CNetMessage* pMsg, uint clientMask, void* UNU order.m_action=msg->m_Action; \ QueueOrder(order, msg->m_Entities, isQueued); \ } while(0) -#define ENTITY_INT_STRING(_msg, _order) do\ - { \ +#define ENTITY_INT_STRING(_msg, _order) \ + do { \ _msg *msg=(_msg *)pMsg; \ isQueued = msg->m_IsQueued != 0; \ order.m_type=CEntityOrder::_order; \ @@ -369,7 +369,7 @@ uint CSimulation::TranslateMessage(CNetMessage* pMsg, uint clientMask, void* UNU order.m_new_obj = newObj; QueueOrder(order, msg->m_Entities, isQueued); } - } while(0) + } break; } diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/PlaceObject.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/PlaceObject.cpp index 396ccf6376..65940127a6 100644 --- a/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/PlaceObject.cpp +++ b/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/PlaceObject.cpp @@ -76,9 +76,9 @@ public: return false; } - bool OnKeyOverride(wxKeyEvent& evt, KeyEventType dir) + bool OnKeyOverride(wxKeyEvent& evt, KeyEventType type) { - switch (dir) + switch (type) { case KEY_CHAR: int key = evt.GetKeyCode(); @@ -129,9 +129,18 @@ public: else return false; } - bool OnKey(PlaceObject* obj, wxKeyEvent& evt, KeyEventType dir) + bool OnKey(PlaceObject* obj, wxKeyEvent& evt, KeyEventType type) { - return obj->OnKeyOverride(evt, dir); + if (type == KEY_CHAR && (evt.GetKeyCode() >= '0' && evt.GetKeyCode() <= '9')) + { + int playerID = evt.GetKeyCode() - '0'; + g_ObjectSettings.SetPlayerID(playerID); + g_ObjectSettings.NotifyObservers(); + obj->SendObjectMsg(true); + return true; + } + else + return obj->OnKeyOverride(evt, type); } void OnTick(PlaceObject* obj, float dt) { @@ -166,9 +175,9 @@ public: else return false; } - bool OnKey(PlaceObject* obj, wxKeyEvent& evt, KeyEventType dir) + bool OnKey(PlaceObject* obj, wxKeyEvent& evt, KeyEventType type) { - return obj->OnKeyOverride(evt, dir); + return obj->OnKeyOverride(evt, type); } void OnTick(PlaceObject* obj, float dt) { diff --git a/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp index 87752a3bc7..f875ce581f 100644 --- a/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp +++ b/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp @@ -243,21 +243,23 @@ static int g_PreviewUnitID = -1; static CStrW g_PreviewUnitName; static bool g_PreviewUnitFloating; -// Returns roughly the largest number smaller than f (i.e. closer to zero) -// (TODO: does this actually work correctly?) -static float flt_minus_epsilon(float f) -{ - return f - (FLT_EPSILON * f); -} - static CVector3D GetUnitPos(const Position& pos, bool floating) { static CVector3D vec; vec = pos.GetWorldSpace(vec, floating); // if msg->pos is 'Unchanged', use the previous pos - // Check whether the position should be clamped to the edges of the world - float xOnMap = clamp(vec.X, 0.f, flt_minus_epsilon((g_Game->GetWorld()->GetTerrain()->GetVerticesPerSide()-1)*CELL_SIZE)); - float zOnMap = clamp(vec.Z, 0.f, flt_minus_epsilon((g_Game->GetWorld()->GetTerrain()->GetVerticesPerSide()-1)*CELL_SIZE)); + // Clamp the position to the edges of the world: + + // Use 'clamp' with a value slightly less than the width, so that converting + // to integer (rounding towards zero) will put it on the tile inside the edge + // instead of just outside + float mapWidth = (g_Game->GetWorld()->GetTerrain()->GetVerticesPerSide()-1)*CELL_SIZE; + float delta = 1e-8f; // fraction of map width (which is around 1e+4 world-space units) + + float xOnMap = clamp(vec.X, 0.f, mapWidth * (1.f - delta)); + float zOnMap = clamp(vec.Z, 0.f, mapWidth * (1.f - delta)); + + // Don't waste time with getExactGroundLevel unless we've changed if (xOnMap != vec.X || zOnMap != vec.Z) { vec.X = xOnMap; diff --git a/source/tools/atlas/GameInterface/View.cpp b/source/tools/atlas/GameInterface/View.cpp index 3458c7f4f2..05222f1249 100644 --- a/source/tools/atlas/GameInterface/View.cpp +++ b/source/tools/atlas/GameInterface/View.cpp @@ -268,9 +268,6 @@ void ViewGame::SaveState(const std::wstring& label, bool onlyEntities) e.position = entity->m_position; e.angle = entity->m_orientation.Y; - // TODO: preserve random actor variations - // TODO: preserve IDs - simState->entities.push_back(e); } @@ -368,11 +365,12 @@ View::~View() View* View::GetView(int /*eRenderView*/ view) { - if (view == AtlasMessage::eRenderView::NONE) return View::GetView_None(); - else if (view == AtlasMessage::eRenderView::GAME) return View::GetView_Game(); - else if (view == AtlasMessage::eRenderView::ACTOR) return View::GetView_Actor(); - else + switch (view) { + case AtlasMessage::eRenderView::NONE: return View::GetView_None(); + case AtlasMessage::eRenderView::GAME: return View::GetView_Game(); + case AtlasMessage::eRenderView::ACTOR: return View::GetView_Actor(); + default: debug_warn("Invalid view type"); return View::GetView_None(); }