Skip to content

Commit

Permalink
Weapon Randomizer: Implement new weapon weights and fix no-RPGs
Browse files Browse the repository at this point in the history
  • Loading branch information
Parik27 committed May 19, 2021
1 parent 1087371 commit 328d8bd
Show file tree
Hide file tree
Showing 12 changed files with 137 additions and 26 deletions.
2 changes: 1 addition & 1 deletion build-count.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
372
379
2 changes: 1 addition & 1 deletion config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ LogSpawnedVehicles = false # Logs all the spawned script vehicles
#######################################################
[WeatherRandomizer]

RandomizeWeather = false # Randomize the weather (properties like sun, rain, etc.)
RandomizeWeather = true # Randomize the weather (properties like sun, rain, etc.)
RandomizeTimecycle = true # Randomize the appearance of the sky/ground.

# CrazyMode = false # Not recommended, makes the game invisible.
Expand Down
8 changes: 8 additions & 0 deletions lib/Parser.hh
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ struct parMemberEnumData : parMemberCommonData
uint8_t field_0x18[16];
void ** m_pTranslationTable;
};

struct parMemberBitsetData : parMemberCommonData
{

uint8_t field_0x18[23];
void ** m_pTranslationTable;
};

#pragma pack(pop)

/*******************************************************/
Expand Down
22 changes: 22 additions & 0 deletions lib/ParserUtils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,25 @@ ParserUtils::FindFieldEnum (parStructureStaticData *data, void *ptr,
return ParserEnumEquate<> (*enumField->m_pTranslationTable,
FindFieldPtr (data, ptr, hash));
}

/*******************************************************/
ParserBitset
ParserUtils::FindFieldBitset (parStructureStaticData *data, void *ptr,
uint32_t hash)
{
parMemberCommonData *field = FindFieldData (data->Params, hash);

if (!field)
throw std::runtime_error ("Failed to find bitset field for parser"
+ std::to_string (hash));

if (field->eType != parMemberType::BITSET)
throw std::runtime_error (
"Bitset field for parser is not of bitset type"
+ std::to_string (hash));

parMemberBitsetData *enumField = static_cast<parMemberBitsetData *> (field);

return ParserBitset (*enumField->m_pTranslationTable,
FindFieldPtr (data, ptr, hash));
}
65 changes: 65 additions & 0 deletions lib/ParserUtils.hh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,53 @@
#include <cstdint>
#include <string_view>

/*******************************************************/
class ParserBitset
{
rage::bitset<32> *pData;

struct TranslationTable
{
uint32_t nHash;
uint32_t nValue;
} * Table;

public:
ParserBitset (void *Table, void *data)
{
pData = reinterpret_cast<rage::bitset<32> *> (data);
this->Table = reinterpret_cast<TranslationTable *> (Table);
}

uint32_t
Translate (uint32_t hash)
{
TranslationTable *t = Table;
while (t->nHash != 0 && t->nValue != -1u)
{
if (t->nHash == hash)
return t->nValue;
t++;
}

return -1;
}

void
Set (uint32_t hash, bool value)
{
uint32_t translated = Translate (hash);
if (translated != -1)
pData->Set (translated, value);
}

bool
operator[] (uint32_t hash)
{
return (*pData)[Translate (hash)];
}
};

/*******************************************************/
template <typename T = uint32_t> class ParserEnumEquate
{
Expand Down Expand Up @@ -106,6 +153,16 @@ public:
return FindFieldEnum (data, (void *) ptr, hash);
}

static ParserBitset FindFieldBitset (parStructureStaticData *data,
void *ptr, uint32_t hash);

template <typename P>
inline static ParserBitset
FindFieldBitset (parStructureStaticData *data, P *ptr, uint32_t hash)
{
return FindFieldBitset (data, (void *) ptr, hash);
}

template <typename T, typename P>
inline static T &
FindFieldPtr (parStructureStaticData *data, P *ptr, uint32_t hash)
Expand Down Expand Up @@ -181,6 +238,14 @@ public:
fieldHash);
}

ParserBitset
Bitset (uint32_t fieldHash)
{
return ParserUtils::FindFieldBitset (GetStaticData (),
static_cast<Class *> (this),
fieldHash);
}

template <typename T>
T &
Get (uint32_t fieldHash)
Expand Down
2 changes: 1 addition & 1 deletion src/common/configDefault.hh
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ LogSpawnedVehicles = false # Logs all the spawned script vehicles
#######################################################
[WeatherRandomizer]
RandomizeWeather = false # Randomize the weather (properties like sun, rain, etc.)
RandomizeWeather = true # Randomize the weather (properties like sun, rain, etc.)
RandomizeTimecycle = true # Randomize the appearance of the sky/ground.
# CrazyMode = false # Not recommended, makes the game invisible.
Expand Down
2 changes: 1 addition & 1 deletion src/misc/cutscenes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class CutSceneRandomizer
InitialiseModelData ()
{
FILE *modelsFile = Rainbomizer::Common::GetRainbomizerDataFile (
"CutsceneModels.txt");
"CutsceneModelsProps.txt");
GetModelsList ().clear ();

if (!modelsFile)
Expand Down
13 changes: 9 additions & 4 deletions src/misc/scaleform.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class ScaleformRandomizer
bool useLastInsult = false)
{
static const int INSULT_ODDS = 10;
ReadInsultsList ();

if (m_MissionFailInsults.empty ())
return;
Expand Down Expand Up @@ -99,31 +100,35 @@ class ScaleformRandomizer
}

/*******************************************************/
bool
static void
ReadInsultsList ()
{
static bool sm_Initialised = false;
if (std::exchange (sm_Initialised, true))
return;

FILE *insultsFile
= Rainbomizer::Common::GetRainbomizerDataFile ("FailMessages.txt");

if (!insultsFile)
return false;
return;

char line[1024] = {0};
while (fgets (line, 512, insultsFile))
{
line[strcspn (line, "\n")] = 0;
m_MissionFailInsults.push_back (line);
m_MissionFailInsults.back () += ' ';
}

return true;
return;
}

public:
/*******************************************************/
ScaleformRandomizer ()
{
InitialiseAllComponents ();
ReadInsultsList ();
REGISTER_HOOK ("89 74 ? ? e8 ? ? ? ? ? 8b cd ? 8b d0 e8", 4,
RandomizeScaleformMethod, void *, void *, int, uint64_t,
uint64_t, char *, ScaleformMethodStruct::ParamStruct *,
Expand Down
2 changes: 1 addition & 1 deletion src/misc/weather.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class WeatherRandomizer
// Config
static inline struct Config
{
bool RandomizeWeather = false;
bool RandomizeWeather = true;
bool RandomizeTimecycle = true;
bool CrazyMode = false;

Expand Down
4 changes: 2 additions & 2 deletions src/peds/peds_PlayerFixes.hh
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ public:
if (sm_Initialised)
return;

sm_Initialised = true;

// Hook for cutscenes to properly get the object model to register for
// the cutscene.
REGISTER_HOOK ("8b d9 40 38 3d ? ? ? ? 75 ? e8", 11,
Expand All @@ -178,8 +180,6 @@ public:
10),
2);

sm_Initialised = true;

// To make UpdatePlayerHash also be called after a call to
// CHANGE_PLAYER_PED (and several other functions). Can also be extended
// to add CPedFactory::CreatePlayer, but I didn't see the need.
Expand Down
2 changes: 1 addition & 1 deletion src/peds/peds_Streaming.hh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class PedRandomizer_Streaming
GetRandomPedIndex ()
{
auto &PedHashes = Rainbomizer::Common::GetPedHashes ();
return GetRandomElement (PedHashes);
return CStreaming::GetModelIndex (GetRandomElement (PedHashes));
}

/*******************************************************/
Expand Down
39 changes: 25 additions & 14 deletions src/weapons/weapons.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class WeaponRandomizer
static inline bool mSkipNextWeaponRandomization;
static inline WeaponEquipMgr mEquipMgr;

static inline std::unordered_map<uint32_t, uint32_t> mValidWeaponGroups;

/*******************************************************/
static void
InitialiseWeaponWeights ()
Expand Down Expand Up @@ -63,15 +65,21 @@ class WeaponRandomizer
}
}

double mean_probability = 1;
double base_probability = 1;

std::vector<double> weights;
for (auto i : mValidWeapons)
{
if (probabilities.count (i))
weights.push_back (probabilities[i]);
else
weights.push_back (mean_probability);
double weight = base_probability;

// Multiply groupWeight with the current weight
if (auto *gW = LookupMap (probabilities, mValidWeaponGroups[i]))
weight = (*gW);

if (auto *weapWeight = LookupMap (probabilities, i))
weight = *weapWeight;

weights.push_back (weight);
}

mDistribution
Expand All @@ -82,15 +90,15 @@ class WeaponRandomizer
static bool
IsValidWeapon (CWeaponInfo &info)
{
switch (info.Equate ("FireType"_joaat).ToHash ())
{
case "PROJECTILE"_joaat:
case "NONE"_joaat: return false;
}
if (info.Equate ("FireType"_joaat).ToHash () == "NONE"_joaat)
return false;

if (info.Get<uint32_t> ("HumanNameHash"_joaat) == "wt_invalid"_joaat)
return false;

if (info.Bitset ("WeaponFlags"_joaat)["Thrown"_joaat])
return false;

return true;
}

Expand All @@ -108,15 +116,18 @@ class WeaponRandomizer

for (auto &info : CWeaponInfoManager::sm_Instance->aItemInfos)
{
uint32_t modelHash = info->Model;
static_assert ("cweaponinfo"_joaat == 0x861905b4);

uint32_t outHash = 0;

if (modelHash && !DoesElementExist (mExceptions, info->Name)
if (info->Model && !DoesElementExist (mExceptions, info->Name)
&& info->GetClassId (outHash) == "cweaponinfo"_joaat
&& IsValidWeapon (*static_cast<CWeaponInfo *> (info)))
mValidWeapons.push_back (info->Name);
{
mValidWeapons.push_back (info->Name);
mValidWeaponGroups[info->Name]
= static_cast<CWeaponInfo *> (info)->Get<uint32_t> (
"Group"_joaat);
}
}

InitialiseWeaponWeights ();
Expand Down

0 comments on commit 328d8bd

Please sign in to comment.