Specific drug types and drug items for background and facilities. (#226)

This commit is contained in:
Andrzej Fałkowski
2023-10-02 19:30:59 +03:00
committed by GitHub
parent 9033e1097a
commit a3be3ecd7e
9 changed files with 227 additions and 41 deletions
+7 -1
View File
@@ -3,6 +3,7 @@
#include "types.h"
#include "DEBUG.H"
#include <map>
const int MAXIMUM_VALID_X_COORDINATE = 16;
const int MINIMUM_VALID_X_COORDINATE = 1;
@@ -223,6 +224,11 @@ enum
NUM_RISKS,
};
enum class FacilityRiskVectorTypes
{
RISK_DRUG_ITEMS,
};
typedef struct FACILITYRISKTYPE
{
// The risks involved with perfoming an assignment at a specific facility.
@@ -231,6 +237,7 @@ typedef struct FACILITYRISKTYPE
INT8 bBaseEffect; // Base result. If negative, result will always be negative. If positive, result will always be positive.
// If 0, result can be either negative or positive.
UINT8 ubRange; // Range of deviation for the base effect.
std::map<FacilityRiskVectorTypes, std::vector<INT16>> valueVectors; // Optional additional data
} FACILITYRISKTYPE;
@@ -333,7 +340,6 @@ typedef struct FACILITYTYPE
std::vector<PRODUCTION_LINE> ProductionData;
} FACILITYTYPE;
#define FACILITYTYPE_SIZEOF_POD offsetof(FACILITYTYPE, ProductionData)
// HEADROCK HAM 3.5: Maximum number of different facility types
#define MAX_NUM_FACILITY_TYPES 255
+20 -3
View File
@@ -34,6 +34,7 @@
#include "Isometric Utils.h"
#include "MilitiaSquads.h"
#include "Tactical Save.h"
#include <random>
INT16 gsSkyriderCostModifier;
// HEADROCK HAM 3.6: Strategic info variable, total of income/costs accumulated for the use of facilities today.
@@ -1808,9 +1809,25 @@ void HandleRisksForSoldierFacilityAssignment( SOLDIERTYPE *pSoldier, UINT8 ubFac
}
// Add effects
CreateItem( ALCOHOL, Item[ALCOHOL].usPortionSize, &gTempObject );
ApplyConsumable( pSoldier, &gTempObject, TRUE, FALSE );
{
std::vector<INT16>& riskDrugItems =
gFacilityTypes[ubFacilityType].AssignmentData[ubAssignmentType].Risk[iCounter].valueVectors[FacilityRiskVectorTypes::RISK_DRUG_ITEMS];
if (riskDrugItems.empty())
{
CreateItem(ALCOHOL, Item[ALCOHOL].usPortionSize, &gTempObject);
ApplyConsumable(pSoldier, &gTempObject, TRUE, FALSE);
}
else
{
INT16 sItemId = riskDrugItems[std::uniform_int_distribution<>(0, riskDrugItems.size() - 1)(std::mt19937{ std::random_device{}() })];
CreateItem(sItemId, Item[sItemId].usPortionSize, &gTempObject);
ApplyConsumable(pSoldier, &gTempObject, TRUE, FALSE);
}
}
//pSoldier->AddDrugValues( DRUG_TYPE_ALCOHOL, Drug[DRUG_TYPE_ALCOHOL].ubDrugEffect, Drug[DRUG_TYPE_ALCOHOL].ubDrugTravelRate, Drug[DRUG_TYPE_ALCOHOL].ubDrugSideEffect );
+94 -28
View File
@@ -39,8 +39,8 @@
// anv: for hourly heli repair
#include "Vehicles.h"
#include "Map Screen Helicopter.h"
// anv: transition to save screen in extreme iron man mode
#include "gameloop.h"
#include "gameloop.h" // anv: transition to save screen in extreme iron man mode
#include <random> // anv: shuffle drug items in hourly update
void HourlyQuestUpdate();
void HourlyLarryUpdate();
@@ -342,6 +342,7 @@ void HourlyQuestUpdate()
}
#define BAR_TEMPTATION 4
#define INVENTORY_DRUG_TEMPTATION 5
// Flugente: abandoned the LarryItems for the new drug system
/*#define NUM_LARRY_ITEMS 6
@@ -377,40 +378,105 @@ void HourlyLarryUpdate()
{
fTookDrugs = FALSE;
if ( pSoldier->bAssignment < ON_DUTY && !pSoldier->flags.fBetweenSectors && pSoldier->bInSector && !( gTacticalStatus.fEnemyInSector || guiCurrentScreen == GAME_SCREEN ) )
const std::vector<INT16> drugItems = pSoldier->GetBackgroundValueVector(BackgroundVectorTypes::BG_DRUGUSE_ITEMS);
const std::vector<INT16> drugTypes = pSoldier->GetBackgroundValueVector(BackgroundVectorTypes::BG_DRUGUSE_TYPES);
if ( pSoldier->bAssignment < ON_DUTY && !pSoldier->flags.fBetweenSectors && !( gTacticalStatus.fEnemyInSector || guiCurrentScreen == GAME_SCREEN ) )
{
// Flugente: reworked this for the new drug system. We now loop over our entire inventory
INT8 invsize = (INT8)pSoldier->inv.size(); // remember inventorysize, so we don't call size() repeatedly
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop) // ... for all items in our inventory ...
{
if ( pSoldier->inv[bLoop].exists() && Item[ pSoldier->inv[bLoop].usItem ].drugtype > 0 )
if (pSoldier->inv[bLoop].exists())
{
pObj = &(pSoldier->inv[bLoop]);
usTemptation = 5;
// any drug will do... I'm not going to create a new tag for sth minor like this
break;
INT16 sCurrentItemId = pSoldier->inv[bLoop].usItem;
INT16 sCurrentDrugType = Item[sCurrentItemId].drugtype;
if (Item[sCurrentItemId].drugtype > 0 && Item[sCurrentItemId].usItemClass & (IC_KIT | IC_MISC))
{
// anv: if drug user has no items or types specified, assume any is valid, otherwise check drug item id or type
if ((drugItems.empty() && drugTypes.empty()) ||
(!drugItems.empty() && std::find(drugItems.begin(), drugItems.end(), sCurrentItemId) != drugItems.end()) ||
(!drugTypes.empty() && std::find(drugTypes.begin(), drugTypes.end(), sCurrentDrugType) != drugTypes.end()))
{
pObj = &(pSoldier->inv[bLoop]);
usTemptation = INVENTORY_DRUG_TEMPTATION;
break;
}
}
}
}
// check to see if we're in a bar sector, if we are, we have access to alcohol
// which may be better than anything we've got...
if ( usTemptation < BAR_TEMPTATION && GetCurrentBalance() >= Item[ ALCOHOL ].usPrice )
INT16 sBarDrugItemId = 0;
if ( usTemptation < BAR_TEMPTATION )
{
if ( pSoldier->bSectorZ == 0 &&
( ( pSoldier->sSectorX == 13 && pSoldier->sSectorY == MAP_ROW_D) ||
( pSoldier->sSectorX == 13 && pSoldier->sSectorY == MAP_ROW_C) ||
( pSoldier->sSectorX == 5 && pSoldier->sSectorY == MAP_ROW_C) ||
( pSoldier->sSectorX == 6 && pSoldier->sSectorY == MAP_ROW_C) ||
( pSoldier->sSectorX == 5 && pSoldier->sSectorY == MAP_ROW_D) ||
( pSoldier->sSectorX == 2 && pSoldier->sSectorY == MAP_ROW_H)
)
)
// sevenfm: check facility
if (pSoldier->bSectorZ == 0)
{
// in a bar!
fBar = TRUE;
usTemptation = BAR_TEMPTATION;
for (UINT16 usFacilityType = 0; usFacilityType < NUM_FACILITY_TYPES; usFacilityType++)
{
// Is this facility here?
if (gFacilityLocations[SECTOR(pSoldier->sSectorX, pSoldier->sSectorY)][usFacilityType].fFacilityHere)
{
for (UINT16 usFacilityAssignment = 0; usFacilityAssignment < NUM_FACILITY_ASSIGNMENTS; usFacilityAssignment++)
{
// is it a place with risk of getting drunk?
if (gFacilityTypes[usFacilityType].AssignmentData[usFacilityAssignment].Risk[RISK_DRUNK].usChance > 0)
{
// anv: check all items available for this risk
const std::vector<INT16>& riskDrugItems =
gFacilityTypes[usFacilityType].AssignmentData[usFacilityAssignment].Risk[RISK_DRUNK].valueVectors[FacilityRiskVectorTypes::RISK_DRUG_ITEMS];
if (riskDrugItems.empty())
{
if (GetCurrentBalance() >= Item[ALCOHOL].usPrice)
{
if ((drugItems.empty() && drugTypes.empty()) ||
(!drugItems.empty() && std::find(drugItems.begin(), drugItems.end(), sBarDrugItemId) != drugItems.end()) ||
(!drugTypes.empty() && std::find(drugTypes.begin(), drugTypes.end(), Item[ALCOHOL].drugtype) != drugTypes.end()))
{
sBarDrugItemId = ALCOHOL;
// Cool.
fBar = TRUE;
}
}
}
else
{
std::vector<INT16> shuffledRiskDrugItems = riskDrugItems;
std::shuffle(shuffledRiskDrugItems.begin(), shuffledRiskDrugItems.end(), std::mt19937{ std::random_device{}() });
for (INT16 sItemId : shuffledRiskDrugItems)
{
if (sItemId < MAXITEMS && Item[sItemId].usItemClass & (IC_KIT | IC_MISC) && GetCurrentBalance() >= Item[sItemId].usPrice)
{
if ((drugItems.empty() && drugTypes.empty()) ||
(!drugItems.empty() && std::find(drugItems.begin(), drugItems.end(), sItemId) != drugItems.end()) ||
(!drugTypes.empty() && std::find(drugTypes.begin(), drugTypes.end(), Item[sItemId].drugtype) != drugTypes.end()))
{
sBarDrugItemId = sItemId;
// Cool.
fBar = TRUE;
// sevenfm: stop searching
break;
}
}
}
}
}
if (fBar)
{
usTemptation = BAR_TEMPTATION;
break;
}
}
}
}
}
}
@@ -473,10 +539,10 @@ void HourlyLarryUpdate()
bBoozeSlot = FindEmptySlotWithin( pSoldier, HANDPOS, NUM_INV_SLOTS );
if ( bBoozeSlot != NO_SLOT )
{
INVTYPE drugItem = Item[sBarDrugItemId];
// take $ from player's account
// silversurfer: changed the price to reflect the changed amount of 25% below
//usCashAmount = Item[ ALCOHOL ].usPrice;
usCashAmount = (UINT16)( Item[ALCOHOL].usPrice / 4.0f );
usCashAmount = (UINT16)(drugItem.usPrice / 4.0f);
AddTransactionToPlayersBook ( TRANSFER_FUNDS_TO_MERC, pSoldier->ubProfile, GetWorldTotalMin(), -( usCashAmount ) );
// give Larry booze here
@@ -484,10 +550,10 @@ void HourlyLarryUpdate()
// Now the bottle will be fully consumed below and vanishes from inventory before the player even gets to see it. This simulates going to a bar to have a drink there.
UINT8 portionsize = 25;
if ( Item[ALCOHOL].usPortionSize > 0 && Item[ALCOHOL].usPortionSize < 25 )
portionsize = Item[ALCOHOL].usPortionSize;
if (drugItem.usPortionSize > 0 && drugItem.usPortionSize < 25)
portionsize = drugItem.usPortionSize;
CreateItem( ALCOHOL, portionsize, &( pSoldier->inv[bBoozeSlot] ) );
CreateItem( sBarDrugItemId, portionsize, &( pSoldier->inv[bBoozeSlot] ) );
ApplyConsumable( pSoldier, &( pSoldier->inv[bBoozeSlot] ), TRUE, FALSE );
}
+30 -2
View File
@@ -41,6 +41,7 @@ typedef enum
typedef struct
{
FACILITYTYPE_PARSE_STAGE curElement;
PARSE_STAGE curGenericElement;
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
INT16 curAssignmentType;
INT16 curRisk;
@@ -168,7 +169,7 @@ facilitytypeStartElementHandle(void *userData, const XML_Char *name, const XML_C
pData->curElement = FACILITYTYPE_TYPE;
// Set all values to default before applying XML data
memset(&pData->curFacilityTypeData, 0, FACILITYTYPE_SIZEOF_POD);
pData->curFacilityTypeData = FACILITYTYPE();
InitFacilityTypeEntry( pData );
//DebugMsg(TOPIC_JA2, DBG_LEVEL_3,"MergeStartElementHandle: setting memory for curMerge");
@@ -405,6 +406,23 @@ facilitytypeStartElementHandle(void *userData, const XML_Char *name, const XML_C
pData->maxReadDepth++;
}
else if (pData->curElement == FACILITYTYPE_RISK &&
pData->curRisk == RISK_DRUNK &&
strcmp(name, "drugitems") == 0)
{
pData->curGenericElement = ELEMENT_VECTOR_OF_NUMBERS;
pData->curElement = FACILITYTYPE_RISK_ELEMENT;
pData->curAssignmentData.Risk[pData->curRisk].valueVectors[FacilityRiskVectorTypes::RISK_DRUG_ITEMS].clear();
pData->maxReadDepth++;
}
else if (pData->curGenericElement == ELEMENT_VECTOR_OF_NUMBERS &&
strcmp(name, "drugitem") == 0)
{
pData->curGenericElement = ELEMENT_VECTOR_OF_NUMBERS_NUMBER;
pData->maxReadDepth++;
}
else if ( pData->curElement == FACILITYTYPE_PRODUCTION &&
( strcmp( name, "szProductionName" ) == 0 ||
strcmp( name, "szAdditionalRequirementTips" ) == 0 ||
@@ -530,6 +548,7 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name)
gFacilityTypes[pData->curIndex].AssignmentData[cnt].Risk[cntB].usChance = pData->curFacilityTypeData.AssignmentData[cnt].Risk[cntB].usChance;
gFacilityTypes[pData->curIndex].AssignmentData[cnt].Risk[cntB].bBaseEffect = pData->curFacilityTypeData.AssignmentData[cnt].Risk[cntB].bBaseEffect;
gFacilityTypes[pData->curIndex].AssignmentData[cnt].Risk[cntB].ubRange = pData->curFacilityTypeData.AssignmentData[cnt].Risk[cntB].ubRange;
gFacilityTypes[pData->curIndex].AssignmentData[cnt].Risk[cntB].valueVectors = pData->curFacilityTypeData.AssignmentData[cnt].Risk[cntB].valueVectors;
}
}
@@ -673,6 +692,7 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name)
pData->curFacilityTypeData.AssignmentData[pData->curAssignmentType].Risk[cnt].usChance = pData->curAssignmentData.Risk[cnt].usChance;
pData->curFacilityTypeData.AssignmentData[pData->curAssignmentType].Risk[cnt].bBaseEffect = pData->curAssignmentData.Risk[cnt].bBaseEffect;
pData->curFacilityTypeData.AssignmentData[pData->curAssignmentType].Risk[cnt].ubRange = pData->curAssignmentData.Risk[cnt].ubRange;
pData->curFacilityTypeData.AssignmentData[pData->curAssignmentType].Risk[cnt].valueVectors = pData->curAssignmentData.Risk[cnt].valueVectors;
}
}
else
@@ -1252,6 +1272,14 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name)
pData->curProductionData.usOptional_PreProducts.push_back( data );
}
}
else if (pData->curGenericElement == ELEMENT_VECTOR_OF_NUMBERS_NUMBER && strcmp(name, "drugitem") == 0)
{
pData->curGenericElement = ELEMENT_VECTOR_OF_NUMBERS;
pData->curElement = FACILITYTYPE_RISK;
INT16 drugValue = (INT16)atol(pData->szCharData);
pData->curAssignmentData.Risk[pData->curRisk].valueVectors[FacilityRiskVectorTypes::RISK_DRUG_ITEMS].push_back(drugValue);
}
pData->maxReadDepth--;
}
@@ -1299,7 +1327,7 @@ BOOLEAN ReadInFacilityTypes(STR fileName, BOOLEAN localizedVersion)
XML_SetCharacterDataHandler(parser, facilitytypeCharacterDataHandle);
memset(&pData, 0, FACILITYTYPEPARSEDATA_SIZE_OF_POD);
pData = facilitytypeParseData();
pData.maxArraySize = MAXITEMS;
pData.curIndex = 0;
+6
View File
@@ -211,6 +211,11 @@ enum {
BG_MAX,
};
enum class BackgroundVectorTypes {
BG_DRUGUSE_TYPES,
BG_DRUGUSE_ITEMS,
};
typedef struct
{
UINT16 uiIndex;
@@ -220,6 +225,7 @@ typedef struct
UINT64 uiFlags; // this flagmask defines what special properties this background has (on/off behaviour)
INT16 value[BG_MAX]; // property values
std::map<BackgroundVectorTypes, std::vector<INT16>> valueVectors; // optional additional data
} BACKGROUND_VALUES;
#define NUM_BACKGROUND 500
+18
View File
@@ -17605,6 +17605,24 @@ INT16 SOLDIERTYPE::GetBackgroundValue( UINT16 aNr )
return 0;
}
const std::vector<INT16>& SOLDIERTYPE::GetBackgroundValueVector(BackgroundVectorTypes backgroundVectorType) const
{
static const std::vector<INT16> emptyVector;
if (UsingBackGroundSystem() && this->ubProfile != NO_PROFILE)
{
const BACKGROUND_VALUES& background = zBackground[gMercProfiles[this->ubProfile].usBackground];
auto iterator = background.valueVectors.find(backgroundVectorType);
if (iterator != background.valueVectors.end())
{
return iterator->second;
}
}
return emptyVector;
}
INT8 SOLDIERTYPE::GetSuppressionResistanceBonus( )
{
INT8 bonus = 0;
+4
View File
@@ -1070,6 +1070,8 @@ public:
INT8 bPathStored; // good for AI to reduct redundancy
};
enum class BackgroundVectorTypes;
class SOLDIERTYPE//last edited at version 102
{
public:
@@ -1954,6 +1956,8 @@ public:
BOOLEAN HasBackgroundFlag( UINT64 aFlag );
INT16 GetBackgroundValue( UINT16 aNr );
const std::vector<INT16>& SOLDIERTYPE::GetBackgroundValueVector(BackgroundVectorTypes backgroundVectorType) const;
INT8 GetSuppressionResistanceBonus(); // bonus to resistance against suppression
INT16 GetMeleeDamageBonus();
INT16 GetAPBonus();
+4 -1
View File
@@ -44,7 +44,10 @@ enum
ELEMENT_DISABILITY_EFFECT,
ELEMENT_DISABILITY_EFFECT_PROPERTY,
ELEMENT_PERSONALITY_EFFECT,
ELEMENT_PERSONALITY_EFFECT_PROPERTY
ELEMENT_PERSONALITY_EFFECT_PROPERTY,
ELEMENT_VECTOR_OF_NUMBERS,
ELEMENT_VECTOR_OF_NUMBERS_NUMBER,
}
typedef PARSE_STAGE;
+44 -6
View File
@@ -41,8 +41,13 @@ backgroundStartElementHandle(void *userData, const XML_Char *name, const XML_Cha
{
pData->curElement = ELEMENT_LIST;
if ( !localizedTextOnly_BG )
memset(pData->curArray,0,sizeof(BACKGROUND_VALUES)*pData->maxArraySize);
if (!localizedTextOnly_BG)
{
for (UINT32 i = 0; i < pData->maxArraySize; i++)
{
pData->curArray[i] = BACKGROUND_VALUES();
}
}
pData->maxReadDepth++; //we are not skipping this element
}
@@ -50,8 +55,8 @@ backgroundStartElementHandle(void *userData, const XML_Char *name, const XML_Cha
{
pData->curElement = ELEMENT;
if ( !localizedTextOnly_BG )
memset(&pData->curBackground,0,sizeof(BACKGROUND_VALUES));
if (!localizedTextOnly_BG)
pData->curBackground = BACKGROUND_VALUES();
pData->maxReadDepth++; //we are not skipping this element
}
@@ -153,6 +158,27 @@ backgroundStartElementHandle(void *userData, const XML_Char *name, const XML_Cha
pData->maxReadDepth++; //we are not skipping this element
}
else if (strcmp(name, "drugtypes") == 0 && pData->curElement == ELEMENT)
{
pData->curElement = ELEMENT_VECTOR_OF_NUMBERS;
pData->curBackground.valueVectors[BackgroundVectorTypes::BG_DRUGUSE_TYPES].clear();
pData->maxReadDepth++; //we are not skipping this element
}
else if (strcmp(name, "drugitems") == 0 && pData->curElement == ELEMENT)
{
pData->curElement = ELEMENT_VECTOR_OF_NUMBERS;
pData->curBackground.valueVectors[BackgroundVectorTypes::BG_DRUGUSE_TYPES].clear();
pData->maxReadDepth++; //we are not skipping this element
}
else if (pData->curElement == ELEMENT_VECTOR_OF_NUMBERS &&
(strcmp(name, "drugtype") == 0 ||
strcmp(name, "drugitem") == 0))
{
pData->curElement = ELEMENT_VECTOR_OF_NUMBERS_NUMBER;
pData->maxReadDepth++; //we are not skipping this element
}
pData->szCharData[0] = '\0';
}
@@ -667,7 +693,19 @@ backgroundEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = ELEMENT;
pData->curBackground.uiFlags |= (UINT16)atol(pData->szCharData) ? BACKGROUND_CIVGROUPLOYAL : 0;
}
else if (strcmp(name, "drugtype") == 0)
{
pData->curElement = ELEMENT_VECTOR_OF_NUMBERS;
INT16 drugValue = (INT16)atol(pData->szCharData);
pData->curBackground.valueVectors[BackgroundVectorTypes::BG_DRUGUSE_TYPES].push_back(drugValue);
}
else if (strcmp(name, "drugitem") == 0)
{
pData->curElement = ELEMENT_VECTOR_OF_NUMBERS;
INT16 drugValue = (INT16)atol(pData->szCharData);
pData->curBackground.valueVectors[BackgroundVectorTypes::BG_DRUGUSE_ITEMS].push_back(drugValue);
}
pData->maxReadDepth--;
}
pData->currentDepth--;
@@ -711,7 +749,7 @@ BOOLEAN ReadInBackgrounds(STR fileName, BOOLEAN localizedVersion)
XML_SetCharacterDataHandler(parser, backgroundCharacterDataHandle);
memset(&pData,0,sizeof(pData));
pData = enemyRankParseData();
pData.curArray = zBackground;
pData.maxArraySize = NUM_BACKGROUND;