New feature: mercs on administration assignment boost the effectivity of other mercs

For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=msg&goto=356696&#msg_356696

Requires GameDir >= r2472

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8665 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2019-02-14 20:48:07 +00:00
parent de8bf8a7d6
commit 47a89e3725
23 changed files with 662 additions and 37 deletions
+11 -2
View File
@@ -2342,8 +2342,7 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
sIconIndex_Assignment = 29;
fDoIcon_Assignment = TRUE;
// determine our skill at detecting disease
sPtsAvailable = pSoldier->stats.bMedical / 2 + NUM_SKILL_TRAITS( pSoldier, DOCTOR_NT ) * 15;
sPtsAvailable = (sPtsAvailable * (100 + pSoldier->GetBackgroundValue( BG_PERC_DISEASE_DIAGNOSE ))) / 100;
sPtsAvailable = pSoldier->GetDiseaseDiagnosePoints();
fShowNumber = TRUE;
fShowMaximum = FALSE;
@@ -2418,6 +2417,16 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
swprintf( sString, L"%3.1f/%d", bPtsAvailable, usMaximumPts );
break;
case ADMINISTRATION:
sIconIndex_Assignment = 36;
fDoIcon_Assignment = TRUE;
fShowCustomText = TRUE;
sPtsAvailable = (INT16)MercPtrs[pFace->ubSoldierID]->GetAdministrationPoints();
bPtsAvailable = GetAdministrationPercentage( MercPtrs[pFace->ubSoldierID]->sSectorX, MercPtrs[pFace->ubSoldierID]->sSectorY );
swprintf( sString, L"%d/%3.1f", sPtsAvailable, bPtsAvailable );
break;
}
// Check for being serviced...
+4 -4
View File
@@ -2963,10 +2963,10 @@ UINT32 UIHandleCAMercShoot( UI_EVENT *pUIEvent )
else
swprintf( zStr, New113Message[MSG113_DO_WE_WANT_SURGERY_BLOODBAG], pTSoldier->GetName(), healwithout_bloodbag, healwith_bloodbag );
wcscpy( gzUserDefinedButton[0], L"Yes*" );
wcscpy( gzUserDefinedButton[1], L"Yes" );
wcscpy( gzUserDefinedButton[2], L"No" );
wcscpy( gzUserDefinedButton[3], L"No" );
wcscpy( gzUserDefinedButton[0], New113Message[MSG113_BLOODBAGOPTIONS_YESSTAR] );
wcscpy( gzUserDefinedButton[1], New113Message[MSG113_BLOODBAGOPTIONS_YES] );
wcscpy( gzUserDefinedButton[2], New113Message[MSG113_BLOODBAGOPTIONS_NO] );
wcscpy( gzUserDefinedButton[3], New113Message[MSG113_BLOODBAGOPTIONS_NO] );
DoMessageBox( MSG_BOX_BASIC_SMALL_BUTTONS, zStr, GAME_SCREEN, (MSG_BOX_FLAG_GENERIC_FOUR_BUTTONS| MSG_BOX_BUTTONS_HORIZONTAL_ORIENTATION), SurgeryRequesterCallback, NULL );
}
else
+40
View File
@@ -2768,6 +2768,30 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
MSYS_EnableRegion( &gUDBFasthelpRegions[iFirstDataRegion + cnt] );
++cnt;
}
//////////////////// ADMINISTRATION MODIFIER
if ( Item[gpItemDescObject->usItem].usAdministrationModifier )
{
CHAR16 pStr2[256];
swprintf( pStr2, szUDBGenSecondaryStatsExplanationsTooltipText[46], Item[gpItemDescObject->usItem].usAdministrationModifier );
swprintf( pStr, L"%s%s", szUDBGenSecondaryStatsTooltipText[46], pStr2 );
SetRegionFastHelpText( &( gUDBFasthelpRegions[iFirstDataRegion + cnt] ), pStr );
MSYS_EnableRegion( &gUDBFasthelpRegions[iFirstDataRegion + cnt] );
++cnt;
}
//////////////////// HACKING MODIFIER
if ( Item[gpItemDescObject->usItem].usHackingModifier )
{
CHAR16 pStr2[256];
swprintf( pStr2, szUDBGenSecondaryStatsExplanationsTooltipText[47], Item[gpItemDescObject->usItem].usHackingModifier );
swprintf( pStr, L"%s%s", szUDBGenSecondaryStatsTooltipText[47], pStr2 );
SetRegionFastHelpText( &( gUDBFasthelpRegions[iFirstDataRegion + cnt] ), pStr );
MSYS_EnableRegion( &gUDBFasthelpRegions[iFirstDataRegion + cnt] );
++cnt;
}
}
//////////////////////////////////////////////////////
@@ -6396,6 +6420,22 @@ void DrawSecondaryStats( OBJECTTYPE * gpItemDescObject )
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoSecondaryIcon, 42, gItemDescGenSecondaryRegions[cnt].sLeft + sOffsetX, gItemDescGenSecondaryRegions[cnt].sTop + sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
++cnt;
}
//////////////////// ADMINISTRATION MODIFIER
if ( ( Item[gpItemDescObject->usItem].usAdministrationModifier && !fComparisonMode ) ||
( fComparisonMode && Item[gpComparedItemDescObject->usItem].usAdministrationModifier ) )
{
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoSecondaryIcon, 44, gItemDescGenSecondaryRegions[cnt].sLeft + sOffsetX, gItemDescGenSecondaryRegions[cnt].sTop + sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
++cnt;
}
//////////////////// HACKING MODIFIER
if ( ( Item[gpItemDescObject->usItem].usHackingModifier && !fComparisonMode ) ||
( fComparisonMode && Item[gpComparedItemDescObject->usItem].usHackingModifier ) )
{
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoSecondaryIcon, 45, gItemDescGenSecondaryRegions[cnt].sLeft + sOffsetX, gItemDescGenSecondaryRegions[cnt].sTop + sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
++cnt;
}
}
void DrawPropertyValueInColour( INT16 iValue, UINT8 ubNumLine, UINT8 ubNumRegion, BOOLEAN fComparisonMode, BOOLEAN fModifier, BOOLEAN fHigherBetter, UINT16 uiOverwriteColour = 0, BOOLEAN fPercentSign = FALSE )
+1
View File
@@ -202,6 +202,7 @@ enum {
BG_FORTIFY_ASSIGNMENT, // modifies effectivity of 'FORTIFICATION' assignment
BG_HACKERSKILL, // hacking skill from 0 to 100, > 0 means hacking is possible
BG_BURIAL_ASSIGNMENT, // modifies effectivity of 'BURIAL' assignment
BG_ADMINISTRATION_ASSIGNMENT, // modifies effectivity of 'ADMINISTRATION' assignment
BG_MAX,
};
+3
View File
@@ -1197,6 +1197,9 @@ typedef struct
// Flugente: fire resistance
INT16 sFireResistance;
// Flugente: a modifier for administration effectiveness
UINT8 usAdministrationModifier;
} INVTYPE;
+104 -2
View File
@@ -19282,6 +19282,19 @@ INT16 SOLDIERTYPE::GetDiseaseResistance( )
return(val);
}
UINT16 SOLDIERTYPE::GetDiseaseDiagnosePoints()
{
// determine our skill at detecting disease
UINT16 skill = this->stats.bMedical / 2 + NUM_SKILL_TRAITS( this, DOCTOR_NT ) * 15;
skill = ( skill * ( 100 + this->GetBackgroundValue( BG_PERC_DISEASE_DIAGNOSE ) ) ) / 100;
FLOAT administrationmodifier = GetAdministrationModifier();
skill *= administrationmodifier;
return skill;
}
FLOAT SOLDIERTYPE::GetBurialPoints( UINT16* apCorpses )
{
if ( this->stats.bLife < OKLIFE || this->bSectorZ || ( this->usSoldierFlagMask & SOLDIER_POW ) )
@@ -19338,7 +19351,9 @@ FLOAT SOLDIERTYPE::GetBurialPoints( UINT16* apCorpses )
}
}
FLOAT totalvalue = val * persmodifier * bestequipmentmodifier * 0.01f;
FLOAT administrationmodifier = GetAdministrationModifier();
FLOAT totalvalue = val * persmodifier * bestequipmentmodifier * administrationmodifier * 0.01f;
// A most awesome merc in Meduna palace, disguised as a soldier, would have a value of 1.15 * 4.63 * 2 = 10.649 at this point.
// This would be the place where we modify our intel gain rate.
@@ -19537,6 +19552,8 @@ FLOAT SOLDIERTYPE::GetConstructionPoints( )
dval = (dval * this->stats.bLife / this->stats.bLifeMax);
dval *= GetAdministrationModifier();
return dval;
}
@@ -20029,7 +20046,9 @@ FLOAT SOLDIERTYPE::GetIntelGain()
FLOAT sectorvalue = log( (FLOAT)ubLocationModifier );
sectorvalue *= sectorvalue / 2.0f;
FLOAT totalvalue = personalvalue * sectorvalue;
FLOAT administrationmodifier = GetAdministrationModifier();
FLOAT totalvalue = personalvalue * sectorvalue * administrationmodifier;
// if we do this disguised as a soldier, we get more info
if ( this->usSoldierFlagMask & SOLDIER_COVERT_SOLDIER )
@@ -20188,6 +20207,89 @@ BOOLEAN SOLDIERTYPE::IsValidBloodDonor()
return TRUE;
}
UINT32 SOLDIERTYPE::GetAdministrationPoints()
{
if ( this->stats.bLife < OKLIFE || this->bSectorZ || ( this->usSoldierFlagMask & SOLDIER_POW ) )
return 0;
// if not on correct assignment, no gain
if ( this->bAssignment != ADMINISTRATION )
return 0;
UINT32 val = 250 + 4 * EffectiveWisdom( this ) + 3 * EffectiveLeadership( this ) + 5 * EffectiveExpLevel( this, FALSE );
// personality/disability modifiers
FLOAT persmodifier = 1.0f;
if ( DoesMercHaveDisability( this, NERVOUS ) ) persmodifier -= 0.01f;
if ( DoesMercHaveDisability( this, FORGETFUL ) ) persmodifier -= 0.60f;
if ( DoesMercHaveDisability( this, PSYCHO ) ) persmodifier -= 0.03f;
if ( DoesMercHaveDisability( this, DEAF ) ) persmodifier -= 0.15f;
if ( DoesMercHaveDisability( this, SHORTSIGHTED ) ) persmodifier -= 0.10f;
if ( gGameOptions.fNewTraitSystem )
{
if ( DoesMercHavePersonality( this, CHAR_TRAIT_SOCIABLE ) ) persmodifier += 0.10f;
if ( DoesMercHavePersonality( this, CHAR_TRAIT_LONER ) ) persmodifier -= 0.10f;
if ( DoesMercHavePersonality( this, CHAR_TRAIT_OPTIMIST ) ) persmodifier += 0.02f;
if ( DoesMercHavePersonality( this, CHAR_TRAIT_ASSERTIVE ) ) persmodifier += 0.08f;
if ( DoesMercHavePersonality( this, CHAR_TRAIT_INTELLECTUAL ) ) persmodifier += 0.15f;
if ( DoesMercHavePersonality( this, CHAR_TRAIT_PRIMITIVE ) ) persmodifier -= 0.15f;
if ( DoesMercHavePersonality( this, CHAR_TRAIT_AGGRESSIVE ) ) persmodifier -= 0.04f;
if ( DoesMercHavePersonality( this, CHAR_TRAIT_PHLEGMATIC ) ) persmodifier -= 0.05f;
if ( DoesMercHavePersonality( this, CHAR_TRAIT_SHOWOFF ) ) persmodifier -= 0.03f;
if ( DoesMercHavePersonality( this, CHAR_TRAIT_COWARD ) ) persmodifier -= 0.07f;
}
// background modifier
persmodifier += ( this->GetBackgroundValue( BG_ADMINISTRATION_ASSIGNMENT ) ) / 100.0f;
// equipment modifier
FLOAT bestequipmentmodifier = 1.0f;
OBJECTTYPE* pObj = NULL;
INT8 invsize = (INT8)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 ( inv[bLoop].exists() == true && Item[inv[bLoop].usItem].usAdministrationModifier )
{
OBJECTTYPE * pObj = &( this->inv[bLoop] ); // ... get pointer for this item ...
if ( pObj != NULL ) // ... if pointer is not obviously useless ...
{
for ( INT16 i = 0; i < pObj->ubNumberOfObjects; ++i )
{
FLOAT modifier = 1.0f + ( Item[inv[bLoop].usItem].usAdministrationModifier * ( *pObj )[i]->data.objectStatus ) / 10000.0f;
if ( modifier > bestequipmentmodifier )
bestequipmentmodifier = modifier;
}
}
}
}
// the best friendly/direct/recruit approach factor can alter the value up to 10%
FLOAT approachmax = max( gMercProfiles[this->ubProfile].usApproachFactor[0], max( gMercProfiles[this->ubProfile].usApproachFactor[1], gMercProfiles[this->ubProfile].usApproachFactor[2] ) );
FLOAT approachmodifier = 1.0f + max( -0.1f, min( 0.1f, (approachmax - 100.0f) / 100.0f ));
UINT32 totalvalue = val * persmodifier * bestequipmentmodifier * approachmodifier / gGameExternalOptions.fAdministrationPointsPerPercent;
ReducePointsForFatigue( this, &totalvalue );
return totalvalue;
}
extern FLOAT GetAdministrationPercentage( INT16 sX, INT16 sY );
FLOAT SOLDIERTYPE::GetAdministrationModifier()
{
if ( ADMINISTRATION_BONUS( this->bAssignment ) )
return 1.0f + GetAdministrationPercentage( this->sSectorX, this->sSectorY ) / 100.0f;
return 1.0f;
}
INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
{
INT8 bBandaged; //,savedOurTurn;
+5
View File
@@ -1950,6 +1950,7 @@ public:
void PrintSleepDesc( CHAR16* apStr );
FLOAT GetDiseaseContactProtection(); // get percentage protection from infections via contact
INT16 GetDiseaseResistance();
UINT16 GetDiseaseDiagnosePoints();
FLOAT GetBurialPoints( UINT16* apCorpses );
// Flugente: hourly breath regen calculation
@@ -2001,6 +2002,10 @@ public:
// Flugente: can we fill a blood bag from this guy ?
BOOLEAN IsValidBloodDonor();
// Flugente: administration assignment
UINT32 GetAdministrationPoints();
FLOAT GetAdministrationModifier();
//////////////////////////////////////////////////////////////////////////////
}; // SOLDIERTYPE;
+6
View File
@@ -139,6 +139,7 @@ backgroundStartElementHandle(void *userData, const XML_Char *name, const XML_Cha
strcmp(name, "fortify_assignment" ) == 0 ||
strcmp(name, "hackerskill" ) == 0 ||
strcmp(name, "burial_assignment" ) == 0 ||
strcmp(name, "administration_assignment" ) == 0 ||
strcmp(name, "druguse") == 0 ||
strcmp(name, "xenophobic") == 0 ||
strcmp(name, "corruptionspread") == 0 ||
@@ -603,6 +604,11 @@ backgroundEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = ELEMENT;
pData->curBackground.value[BG_BURIAL_ASSIGNMENT] = min( 1000, max( -50, (INT16)atol( pData->szCharData ) ) );
}
else if ( strcmp( name, "administration_assignment" ) == 0 )
{
pData->curElement = ELEMENT;
pData->curBackground.value[BG_ADMINISTRATION_ASSIGNMENT] = min( 1000, max( -50, (INT16)atol( pData->szCharData ) ) );
}
else if(strcmp(name, "druguse") == 0)
{
pData->curElement = ELEMENT;