Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Strategic/Campaign Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand All @@ -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;

Expand Down Expand Up @@ -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
Expand Down
23 changes: 20 additions & 3 deletions Strategic/Facilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 );

Expand Down
122 changes: 94 additions & 28 deletions Strategic/Hourly Update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
}
}
}
}
}

Expand Down Expand Up @@ -473,21 +539,21 @@ 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
// silversurfer: only give the merc a 25% bottle. This fixes the problem that the bottle of alcohol can go to any inventory slot even one that isn't available.
// 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 );
}
Expand Down
32 changes: 30 additions & 2 deletions Strategic/XML_FacilityTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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 ||
Expand Down Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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--;
}
Expand Down Expand Up @@ -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;

Expand Down
6 changes: 6 additions & 0 deletions Tactical/Interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ enum {
BG_MAX,
};

enum class BackgroundVectorTypes {
BG_DRUGUSE_TYPES,
BG_DRUGUSE_ITEMS,
};

typedef struct
{
UINT16 uiIndex;
Expand All @@ -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
Expand Down
18 changes: 18 additions & 0 deletions Tactical/Soldier Control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions Tactical/Soldier Control.h
Original file line number Diff line number Diff line change
Expand Up @@ -1070,6 +1070,8 @@ class STRUCT_Pathing//last edited at version 102
INT8 bPathStored; // good for AI to reduct redundancy
};

enum class BackgroundVectorTypes;

class SOLDIERTYPE//last edited at version 102
{
public:
Expand Down Expand Up @@ -1954,6 +1956,8 @@ class SOLDIERTYPE//last edited at version 102
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();
Expand Down
Loading