Skip to content

Commit ea2411c

Browse files
committed
Merge branch 'TheSuperHackers:main' into okji/feat/deterministic-math
2 parents b71bc59 + aa2b09d commit ea2411c

646 files changed

Lines changed: 4013 additions & 12977 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Core/GameEngine/Include/Common/GameAudio.h

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -383,55 +383,4 @@ class AudioManager : public SubsystemInterface
383383
Bool m_disallowSpeech : 1;
384384
};
385385

386-
// TheSuperHackers @feature helmutbuhler 17/05/2025
387-
// AudioManager that does nothing. Used for Headless Mode.
388-
class AudioManagerDummy : public AudioManager
389-
{
390-
#if defined(RTS_DEBUG)
391-
virtual void audioDebugDisplay(DebugDisplayInterface* dd, void* userData, FILE* fp) {}
392-
#endif
393-
virtual void stopAudio(AudioAffect which) override {}
394-
virtual void pauseAudio(AudioAffect which) override {}
395-
virtual void resumeAudio(AudioAffect which) override {}
396-
virtual void pauseAmbient(Bool shouldPause) override {}
397-
virtual void killAudioEventImmediately(AudioHandle audioEvent) override {}
398-
virtual void nextMusicTrack() override {}
399-
virtual void prevMusicTrack() override {}
400-
virtual Bool isMusicPlaying() const override { return false; }
401-
virtual Bool hasMusicTrackCompleted(const AsciiString& trackName, Int numberOfTimes) const override { return false; }
402-
virtual AsciiString getMusicTrackName() const override { return ""; }
403-
virtual void openDevice() override {}
404-
virtual void closeDevice() override {}
405-
virtual void* getDevice() override { return nullptr; }
406-
virtual void notifyOfAudioCompletion(UnsignedInt audioCompleted, UnsignedInt flags) override {}
407-
virtual UnsignedInt getProviderCount() const override { return 0; };
408-
virtual AsciiString getProviderName(UnsignedInt providerNum) const override { return ""; }
409-
virtual UnsignedInt getProviderIndex(AsciiString providerName) const override { return 0; }
410-
virtual void selectProvider(UnsignedInt providerNdx) override {}
411-
virtual void unselectProvider() override {}
412-
virtual UnsignedInt getSelectedProvider() const override { return 0; }
413-
virtual void setSpeakerType(UnsignedInt speakerType) override {}
414-
virtual UnsignedInt getSpeakerType() override { return 0; }
415-
virtual UnsignedInt getNum2DSamples() const override { return 0; }
416-
virtual UnsignedInt getNum3DSamples() const override { return 0; }
417-
virtual UnsignedInt getNumStreams() const override { return 0; }
418-
virtual Bool doesViolateLimit(AudioEventRTS* event) const override { return false; }
419-
virtual Bool isPlayingLowerPriority(AudioEventRTS* event) const override { return false; }
420-
virtual Bool isPlayingAlready(AudioEventRTS* event) const override { return false; }
421-
virtual Bool isObjectPlayingVoice(UnsignedInt objID) const override { return false; }
422-
virtual void adjustVolumeOfPlayingAudio(AsciiString eventName, Real newVolume) override {}
423-
virtual void removePlayingAudio(AsciiString eventName) override {}
424-
virtual void removeAllDisabledAudio() override {}
425-
virtual Bool has3DSensitiveStreamsPlaying() const override { return false; }
426-
virtual void* getHandleForBink() override { return nullptr; }
427-
virtual void releaseHandleForBink() override {}
428-
virtual void friend_forcePlayAudioEventRTS(const AudioEventRTS* eventToPlay) override {}
429-
virtual void setPreferredProvider(AsciiString providerNdx) override {}
430-
virtual void setPreferredSpeaker(AsciiString speakerType) override {}
431-
virtual Real getFileLengthMS(AsciiString strToLoad) const override { return -1; }
432-
virtual void closeAnySamplesUsingFile(const void* fileToClose) override {}
433-
virtual void setDeviceListenerPosition() override {}
434-
};
435-
436-
437386
extern AudioManager *TheAudio;

Core/GameEngine/Include/Common/INI.h

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,11 @@ typedef void (*BuildMultiIniFieldProc)(MultiIniFieldParse& p);
160160
//-------------------------------------------------------------------------------------------------
161161
class INI
162162
{
163-
INI(const INI&);
164-
INI& operator=(const INI&);
163+
INI(const INI&) CPP_11(= delete);
164+
INI& operator=(const INI&) CPP_11(= delete);
165165

166166
public:
167-
168167
INI();
169-
~INI();
170168

171169
// TheSuperHackers @feature xezon 19/08/2025
172170
// Load a specific INI file by name and/or INI files from a directory (and its subdirectories).
@@ -251,11 +249,12 @@ class INI
251249
AsciiString getFilename() const { return m_filename; }
252250
INILoadType getLoadType() const { return m_loadType; }
253251
UnsignedInt getLineNum() const { return m_lineNum; }
254-
const char *getSeps() const { return m_seps; }
255-
const char *getSepsPercent() const { return m_sepsPercent; }
256-
const char *getSepsColon() const { return m_sepsColon; }
257-
const char *getSepsQuote() { return m_sepsQuote; }
258252
Bool isEOF() const { return m_endOfFile; }
253+
static const char *getSeps() { return " \n\r\t="; } ///< default delimiters for strtok parsing
254+
static const char *getSepsPercent() { return " \n\r\t=%%"; } ///< default delimiters & percent delimiter
255+
static const char *getSepsColon() { return " \n\r\t=:"; } ///< default delimiters & colon delimiter
256+
static const char *getSepsQuote() { return "\"\n="; } ///< delimiters to represent a quoted ascii string
257+
static const char *getEndToken() { return "End"; } ///< token to represent an end of data block
259258

260259
void initFromINI( void *what, const FieldParse* parseTable );
261260
void initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList );
@@ -321,20 +320,19 @@ class INI
321320
static void parseVeterancyLevelFlags(INI* ini, void* instance, void* store, const void* userData);
322321
static void parseSoundsList( INI* ini, void *instance, void *store, const void* /*userData*/ );
323322

324-
325323
/**
326-
return the next token. if seps is null (or omitted), the standard seps are used.
324+
return the next token. if seps is not specified, the standard seps are used.
327325
328326
this will *never* return null; if there are no more tokens, an exception will be thrown.
329327
*/
330-
const char* getNextToken(const char* seps = nullptr);
328+
static const char* getNextToken(const char* seps = getSeps());
331329

332330
/**
333331
just like getNextToken(), except that null is returned if no more tokens are present
334332
(rather than throwing an exception). usually you should call getNextToken(),
335333
but for some cases this is handier (ie, parsing a variable-length number of tokens).
336334
*/
337-
const char* getNextTokenOrNull(const char* seps = nullptr);
335+
static const char* getNextTokenOrNull(const char* seps = getSeps());
338336

339337
/**
340338
This is called when the next thing you expect is something like:
@@ -346,7 +344,7 @@ class INI
346344
347345
If "Tag" is not the next token, an error is thrown.
348346
*/
349-
const char* getNextSubToken(const char* expected);
347+
static const char* getNextSubToken(const char* expected);
350348

351349
/**
352350
return the next ascii string. this is usually the same the result of getNextToken(),
@@ -400,14 +398,9 @@ class INI
400398
unsigned m_readBufferUsed; ///< number of bytes in read buffer
401399

402400
AsciiString m_filename; ///< filename of file currently loading
403-
INILoadType m_loadType; ///< load time for current file
401+
INILoadType m_loadType; ///< load type for current file
404402
UnsignedInt m_lineNum; ///< current line number that's been read
405403
char m_buffer[ INI_MAX_CHARS_PER_LINE+1 ];///< buffer to read file contents into
406-
const char *m_seps; ///< for strtok parsing
407-
const char *m_sepsPercent; ///< m_seps with percent delimiter as well
408-
const char *m_sepsColon; ///< m_seps with colon delimiter as well
409-
const char *m_sepsQuote; ///< token to represent a quoted ascii string
410-
const char *m_blockEndToken; ///< token to represent end of data block
411404
Bool m_endOfFile; ///< TRUE when we've hit EOF
412405
#ifdef DEBUG_CRASHING
413406
char m_curBlockStart[ INI_MAX_CHARS_PER_LINE+1 ]; ///< first line of cur block

Core/GameEngine/Include/GameClient/View.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "Common/Snapshot.h"
3535
#include "Lib/BaseType.h"
3636
#include "WW3D2/coltype.h" ///< we don't generally do this, but we need the W3D collision types
37+
#include "WWMath/wwmath.h"
3738

3839
#define DEFAULT_VIEW_WIDTH 640
3940
#define DEFAULT_VIEW_HEIGHT 480
@@ -50,7 +51,9 @@ enum FilterTypes CPP_11(: Int);
5051
enum FilterModes CPP_11(: Int);
5152

5253
// ------------------------------------------------------------------------------------------------
53-
// ------------------------------------------------------------------------------------------------
54+
constexpr const Real ViewDefaultPitchRadians = DEG_TO_RADF(37.5f);
55+
constexpr const Real ViewDefaultYawRadians = DEG_TO_RADF(0.0f);
56+
5457
// ------------------------------------------------------------------------------------------------
5558
enum PickType CPP_11(: Int)
5659
{
@@ -177,8 +180,11 @@ class View : public Snapshot
177180

178181
virtual void setAngle( Real radians ); ///< Rotate the view around the vertical axis to the given angle (yaw)
179182
virtual Real getAngle() { return m_angle; } ///< Return current camera angle
183+
virtual Real getDefaultAngle() { return m_defaultAngle; } ///< Return current default camera angle
180184
virtual void setPitch( Real radians ); ///< Rotate the view around the horizontal axis to the given angle (pitch)
181185
virtual Real getPitch() { return m_pitch; } ///< Return current camera pitch
186+
virtual void setDefaultPitch( Real radians ); ///< Set new default camera pitch. It affects the camera distance to the ground
187+
virtual Real getDefaultPitch() { return m_defaultPitch; } ///< Return current default camera pitch
182188
virtual void setAngleToDefault(); ///< Set the view angle back to default
183189
virtual void setPitchToDefault(); ///< Set the view pitch back to default
184190
void setPosition( const Coord3D *pos ) { m_pos = *pos; }
@@ -199,6 +205,7 @@ class View : public Snapshot
199205
Bool userSetAngle(Real radians) { return doUserAction(&View::setAngle, radians); }
200206
Bool userSetAngleToDefault() { return doUserAction(&View::setAngleToDefault); }
201207
Bool userSetPitch(Real radians) { return doUserAction(&View::setPitch, radians); }
208+
Bool userSetDefaultPitch(Real radians) { return doUserAction(&View::setDefaultPitch, radians); }
202209
Bool userSetPitchToDefault() { return doUserAction(&View::setPitchToDefault); }
203210
Bool userZoom(Real height) { return doUserAction(&View::zoom, height); }
204211
Bool userSetZoom(Real z) { return doUserAction(&View::setZoom, z); }
@@ -401,8 +408,8 @@ class ViewDummy : public View
401408
}
402409
virtual void screenToTerrain( const ICoord2D *screen, Coord3D *world ) override {}
403410
virtual void screenToWorldAtZ( const ICoord2D *s, Coord3D *w, Real z ) override {}
404-
virtual void drawView( void ) override {}
405-
virtual void updateView(void) override {}
411+
virtual void drawView() override {}
412+
virtual void updateView() override {}
406413
virtual void stepView() override {}
407414
virtual void setGuardBandBias( const Coord2D *gb ) override {}
408415
virtual Bool isDoingScriptedCamera() override { return false; }

Core/GameEngine/Source/Common/INI/INI.cpp

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -180,26 +180,14 @@ INI::INI()
180180
m_filename = "None";
181181
m_loadType = INI_LOAD_INVALID;
182182
m_lineNum = 0;
183-
m_seps = " \n\r\t="; ///< make sure you update m_sepsPercent/m_sepsColon as well
184-
m_sepsPercent = " \n\r\t=%%";
185-
m_sepsColon = " \n\r\t=:";
186-
m_sepsQuote = "\"\n="; ///< stop at " = EOL
187-
m_blockEndToken = "END";
188-
m_endOfFile = FALSE;
189183
m_buffer[0] = 0;
184+
m_endOfFile = FALSE;
190185
#ifdef DEBUG_CRASHING
191186
m_curBlockStart[0] = 0;
192187
#endif
193188

194189
}
195190

196-
//-------------------------------------------------------------------------------------------------
197-
//-------------------------------------------------------------------------------------------------
198-
INI::~INI()
199-
{
200-
201-
}
202-
203191
//-------------------------------------------------------------------------------------------------
204192
UnsignedInt INI::loadFileDirectory( AsciiString fileDirName, INILoadType loadType, Xfer *pXfer, Bool subdirs )
205193
{
@@ -397,7 +385,7 @@ UnsignedInt INI::load( AsciiString filename, INILoadType loadType, Xfer *pXfer )
397385
AsciiString currentLine = m_buffer;
398386

399387
// the first word is the type of data we're processing
400-
const char *token = strtok( m_buffer, m_seps );
388+
const char *token = strtok( m_buffer, getSeps() );
401389
if( token )
402390
{
403391
INIBlockParse parse = findBlockParse(token);
@@ -710,7 +698,7 @@ void INI::parseAsciiStringVector( INI* ini, void * /*instance*/, void *store, co
710698
{
711699
std::vector<AsciiString>* asv = (std::vector<AsciiString>*)store;
712700
asv->clear();
713-
for (const char *token = ini->getNextTokenOrNull(); token != nullptr; token = ini->getNextTokenOrNull())
701+
for (const char *token = ini->getNextTokenOrNull(); token; token = ini->getNextTokenOrNull())
714702
{
715703
asv->push_back(token);
716704
}
@@ -723,7 +711,7 @@ void INI::parseAsciiStringVectorAppend( INI* ini, void * /*instance*/, void *sto
723711
std::vector<AsciiString>* asv = (std::vector<AsciiString>*)store;
724712
// nope, don't clear. duh.
725713
// asv->clear();
726-
for (const char *token = ini->getNextTokenOrNull(); token != nullptr; token = ini->getNextTokenOrNull())
714+
for (const char *token = ini->getNextTokenOrNull(); token; token = ini->getNextTokenOrNull())
727715
{
728716
asv->push_back(token);
729717
}
@@ -735,7 +723,7 @@ void INI::parseAsciiStringVectorAppend( INI* ini, void * /*instance*/, void *sto
735723
{
736724
ScienceVec* asv = (ScienceVec*)store;
737725
asv->clear();
738-
for (const char *token = ini->getNextTokenOrNull(); token != nullptr; token = ini->getNextTokenOrNull())
726+
for (const char *token = ini->getNextTokenOrNull(); token; token = ini->getNextTokenOrNull())
739727
{
740728
if (stricmp(token, "None") == 0)
741729
{
@@ -952,7 +940,7 @@ void INI::parseBitString32( INI* ini, void * /*instance*/, void *store, const vo
952940
Bool foundAddOrSub = false;
953941

954942
// loop through all tokens
955-
for (const char *token = ini->getNextTokenOrNull(); token != nullptr; token = ini->getNextTokenOrNull())
943+
for (const char *token = ini->getNextTokenOrNull(); token; token = ini->getNextTokenOrNull())
956944
{
957945
if (stricmp(token, "NONE") == 0)
958946
{
@@ -1528,7 +1516,7 @@ void INI::initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList
15281516
if( field )
15291517
{
15301518

1531-
if( stricmp( field, m_blockEndToken ) == 0 )
1519+
if( stricmp( field, getEndToken() ) == 0 )
15321520
{
15331521
done = TRUE;
15341522
}
@@ -1580,7 +1568,7 @@ void INI::initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList
15801568

15811569
done = TRUE;
15821570
DEBUG_CRASH( ("Error parsing block '%s', in INI file '%s'. Missing '%s' token",
1583-
m_curBlockStart, getFilename().str(), m_blockEndToken) );
1571+
m_curBlockStart, getFilename().str(), getEndToken()) );
15841572
throw INI_MISSING_END_TOKEN;
15851573

15861574
}
@@ -1592,7 +1580,6 @@ void INI::initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList
15921580
//-------------------------------------------------------------------------------------------------
15931581
/*static*/ const char* INI::getNextToken(const char* seps)
15941582
{
1595-
if (!seps) seps = getSeps();
15961583
const char *token = ::strtok(nullptr, seps);
15971584
if (!token)
15981585
throw INI_INVALID_DATA;
@@ -1602,7 +1589,6 @@ void INI::initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList
16021589
//-------------------------------------------------------------------------------------------------
16031590
/*static*/ const char* INI::getNextTokenOrNull(const char* seps)
16041591
{
1605-
if (!seps) seps = getSeps();
16061592
const char *token = ::strtok(nullptr, seps);
16071593
return token;
16081594
}
@@ -1618,8 +1604,17 @@ void INI::initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList
16181604
template <typename Type>
16191605
Type scanType(std::string_view token)
16201606
{
1621-
// TheSuperHackers @info std::from_chars cannot parse "-1" as uint32 so the result needs to be int64 for integers.
1622-
std::conditional_t<std::is_integral_v<Type>, Int64, Real> result{};
1607+
DEBUG_ASSERTCRASH(!token.empty(), ("token is not expected to be empty"));
1608+
1609+
// Unlike sscanf, std::from_chars cannot parse "+".
1610+
// Consume the plus symbol to accommodate custom ini files that have numbers prefixed with a plus.
1611+
if (token[0] == '+')
1612+
{
1613+
token.remove_prefix(1);
1614+
}
1615+
1616+
// Unlike sscanf, std::from_chars cannot parse "-" as unsigned integer.
1617+
std::conditional_t<std::is_integral_v<Type>, Int64, Type> result{};
16231618
const auto [ptr, ec] = std::from_chars(token.data(), token.data() + token.size(), result);
16241619

16251620
if (ec != std::errc{})
@@ -1867,12 +1862,10 @@ void INI::parseSoundsList( INI* ini, void *instance, void *store, const void* /*
18671862
std::vector<AsciiString> *vec = (std::vector<AsciiString>*) store;
18681863
vec->clear();
18691864

1870-
const char* SEPS = " \t,=";
1871-
const char *c = ini->getNextTokenOrNull(SEPS);
1872-
while ( c )
1865+
constexpr const char* Seps = " \t,=";
1866+
for (const char* token = ini->getNextTokenOrNull(Seps); token; token = ini->getNextTokenOrNull(Seps))
18731867
{
1874-
vec->push_back( c );
1875-
c = ini->getNextTokenOrNull(SEPS);
1868+
vec->push_back(token);
18761869
}
18771870
}
18781871

Core/GameEngine/Source/GameClient/GUI/GameWindow.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,7 +1579,6 @@ void GameWinDefaultTooltip( GameWindow *window,
15791579
WinInstanceData *instData,
15801580
UnsignedInt mouse )
15811581
{
1582-
return;
15831582

15841583
}
15851584

@@ -1589,8 +1588,6 @@ void GameWinDefaultTooltip( GameWindow *window,
15891588
void GameWinDefaultDraw( GameWindow *window, WinInstanceData *instData )
15901589
{
15911590

1592-
return;
1593-
15941591
}
15951592

15961593
// GameWindow::winSetEnabledImage =============================================

Core/GameEngine/Source/GameClient/Input/Mouse.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,8 @@ void Mouse::createStreamMessages()
824824
{
825825
msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_WHEEL );
826826
msg->appendPixelArgument( m_currMouse.pos );
827-
msg->appendIntegerArgument( m_currMouse.wheelPos / 120 ); // wheel delta
827+
// TheSuperHackers @bugfix Use float wheel delta to preserve fractional values from touchpad input
828+
msg->appendRealArgument( m_currMouse.wheelPos / (Real)MOUSE_WHEEL_DELTA );
828829
msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
829830
}
830831

Core/GameEngine/Source/GameClient/System/ParticleSys.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3384,6 +3384,8 @@ void ParticleSystemManager::xfer( Xfer *xfer )
33843384
}
33853385
else
33863386
{
3387+
DEBUG_ASSERTCRASH(m_allParticleSystemList.empty(), ("ParticleSystemManager: particle systems list is expected empty at start of xfer-load."));
3388+
33873389
const ParticleSystemTemplate *systemTemplate;
33883390

33893391
// read each particle system

0 commit comments

Comments
 (0)