New ability: a disguised spy can distract unalerted enemies, making it easier to sneak by.

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

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8528 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2018-02-25 19:07:31 +00:00
parent c8e9a3fb8e
commit 3bbdd4a23a
22 changed files with 339 additions and 20 deletions
+88 -6
View File
@@ -483,6 +483,86 @@ void BeginCivQuote( SOLDIERTYPE *pCiv, UINT16 ubCivQuoteID, UINT16 ubEntryID, IN
gCivQuoteData.pCiv = pCiv;
}
void BeginChatQuote( SOLDIERTYPE *pCiv, INT16 sX, INT16 sY )
{
VIDEO_OVERLAY_DESC VideoOverlayDesc;
// OK, do we have another on?
if ( gCivQuoteData.bActive )
{
// Delete?
ShutDownQuoteBox( TRUE );
}
if ( pCiv->bTeam == gbPlayerNum )
swprintf( gzCivQuote, L"\"%s\"", szChatTextSpy[Random( 24 )] );
else
swprintf( gzCivQuote, L"\"%s\"", szChatTextEnemy[Random( 24 )] );
// Create video oeverlay....
memset( &VideoOverlayDesc, 0, sizeof( VIDEO_OVERLAY_DESC ) );
// Prepare text box
gCivQuoteData.iDialogueBox = PrepareMercPopupBox( gCivQuoteData.iDialogueBox, BASIC_MERC_POPUP_BACKGROUND, BASIC_MERC_POPUP_BORDER, gzCivQuote, DIALOGUE_DEFAULT_WIDTH, 0, 0, 0, &gusCivQuoteBoxWidth, &gusCivQuoteBoxHeight );
// Flugente: have the box appear a bit above the soldier. Otherwise it will obstruct us from aiming at him, which is annoying if it happens very often
sY -= 30;
// OK, find center for box......
sX = sX - ( gusCivQuoteBoxWidth / 2 );
sY = sY - ( gusCivQuoteBoxHeight / 2 );
// OK, limit to screen......
{
if ( sX < 0 )
{
sX = 0;
}
// CHECK FOR LEFT/RIGHT
if ( ( sX + gusCivQuoteBoxWidth ) > SCREEN_WIDTH )
{
sX = SCREEN_WIDTH - gusCivQuoteBoxWidth;
}
// Now check for top
if ( sY < gsVIEWPORT_WINDOW_START_Y )
{
sY = gsVIEWPORT_WINDOW_START_Y;
}
// Check for bottom
if ( ( sY + gusCivQuoteBoxHeight ) > ( SCREEN_HEIGHT - INV_INTERFACE_HEIGHT ) )
{
sY = ( SCREEN_HEIGHT - INV_INTERFACE_HEIGHT ) - gusCivQuoteBoxHeight;
}
}
VideoOverlayDesc.sLeft = sX;
VideoOverlayDesc.sTop = sY;
VideoOverlayDesc.sRight = VideoOverlayDesc.sLeft + gusCivQuoteBoxWidth;
VideoOverlayDesc.sBottom = VideoOverlayDesc.sTop + gusCivQuoteBoxHeight;
VideoOverlayDesc.sX = VideoOverlayDesc.sLeft;
VideoOverlayDesc.sY = VideoOverlayDesc.sTop;
VideoOverlayDesc.BltCallback = RenderCivQuoteBoxOverlay;
gCivQuoteData.iVideoOverlay = RegisterVideoOverlay( 0, &VideoOverlayDesc );
//Define main region
MSYS_DefineRegion( &( gCivQuoteData.MouseRegion ), VideoOverlayDesc.sLeft, VideoOverlayDesc.sTop, VideoOverlayDesc.sRight, VideoOverlayDesc.sBottom, MSYS_PRIORITY_HIGHEST,
CURSOR_NORMAL, MSYS_NO_CALLBACK, QuoteOverlayClickCallback );
// Add region
MSYS_AddRegion( &( gCivQuoteData.MouseRegion ) );
gCivQuoteData.bActive = TRUE;
gCivQuoteData.uiTimeOfCreation = GetJA2Clock();
gCivQuoteData.uiDelayTime = FindDelayForString( gzCivQuote ) + 500;
gCivQuoteData.pCiv = pCiv;
}
UINT16 DetermineCivQuoteEntry( SOLDIERTYPE *pCiv, UINT16 *pubCivHintToUse, BOOLEAN fCanUseHints )
{
UINT8 ubCivType;
@@ -878,7 +958,6 @@ void HandleCivQuote( )
void StartCivQuote( SOLDIERTYPE *pCiv )
{
UINT16 ubCivQuoteID;
INT16 sX, sY;
UINT16 ubEntryID = 0;
INT16 sScreenX, sScreenY;
UINT16 ubCivHintToUse;
@@ -975,17 +1054,15 @@ void StartCivQuote( SOLDIERTYPE *pCiv )
// Determine location...
// Get location of civ on screen.....
GetSoldierScreenPos( pCiv, &sScreenX, &sScreenY );
sX = sScreenX;
sY = sScreenY;
// begin quote
BeginCivQuote( pCiv, ubCivQuoteID, ubEntryID, sX, sY );
BeginCivQuote( pCiv, ubCivQuoteID, ubEntryID, sScreenX, sScreenY );
// Increment use
if ( ubCivQuoteID != CIV_QUOTE_HINT )
{
//pCiv->bCurrentCivQuoteDelta++;
CivQuoteDelta++;
++CivQuoteDelta;
/*
if ( pCiv->bCurrentCivQuoteDelta == 2 )
{
@@ -2010,4 +2087,9 @@ void ShowTauntPopupBox( SOLDIERTYPE *pCiv, STR16 gzTauntQuote )
gCivQuoteData.uiDelayTime = min( gTauntsSettings.sMaxDelay , max( gTauntsSettings.sMinDelay, FindDelayForString( gzTauntQuote ) + gTauntsSettings.sModDelay ) );
gCivQuoteData.pCiv = pCiv;
}
}
BOOLEAN CivQuoteActive()
{
return gCivQuoteData.bActive;
}
+3
View File
@@ -172,5 +172,8 @@ BOOLEAN LoadCivQuotesFromLoadGameFile( HWFILE hFile );
BOOLEAN ShutDownQuoteBoxIfActive( );
void BeginCivQuote( SOLDIERTYPE *pCiv, UINT16 ubCivQuoteID, UINT16 ubEntryID, INT16 sX, INT16 sY );
void BeginChatQuote( SOLDIERTYPE *pCiv, INT16 sX, INT16 sY );
BOOLEAN CivQuoteActive();
#endif
+85 -1
View File
@@ -10672,6 +10672,32 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[ STR_PRISONER_REFUSE_TAKE_PRISONERS ] );
}
}
// we distract the enemy by essentially talking them to death
else if ( ubExitValue == 3 )
{
// Flugente: if we are disguised and talk to a non-profile NPC, we will continue to 'chat' with the enemy as long as we aren't ordered to do something else.
// This way we can easily order our spies to 'distract 'enemies'
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) &&
pSoldier->bTeam == gbPlayerNum &&
MercPtrs[prisonerdialoguetargetID] &&
MercPtrs[prisonerdialoguetargetID]->bTeam == ENEMY_TEAM &&
MercPtrs[prisonerdialoguetargetID]->ubProfile == NO_PROFILE &&
MercPtrs[prisonerdialoguetargetID]->aiData.bAlertStatus < STATUS_RED &&
!MercPtrs[prisonerdialoguetargetID]->RecognizeAsCombatant( gusSelectedSoldier ) )
{
// both soldiers face each other
pSoldier->EVENT_SetSoldierDesiredDirection( GetDirectionToGridNoFromGridNo( pSoldier->sGridNo, MercPtrs[prisonerdialoguetargetID]->sGridNo ) );
MercPtrs[prisonerdialoguetargetID]->EVENT_SetSoldierDesiredDirection( GetDirectionToGridNoFromGridNo( MercPtrs[prisonerdialoguetargetID]->sGridNo, pSoldier->sGridNo ) );
MercPtrs[prisonerdialoguetargetID]->usChatPartnerID = gusSelectedSoldier;
pSoldier->usChatPartnerID = prisonerdialoguetargetID;
}
else
{
// normal dialog
StartCivQuote( MercPtrs[prisonerdialoguetargetID] );
}
}
else
{
// normal dialog
@@ -10681,6 +10707,50 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
ReduceAttackBusyCount( );
}
// Flugente: disguised mercs can distract enemies by talking to them. In order to display that, we sometimes display excerpts of their 'chats'
void CheckChatPartners()
{
if ( guiCurrentScreen == GAME_SCREEN )
{
if ( !CivQuoteActive() )
{
static BOOLEAN fMercQuoteThisTime = TRUE;
SOLDIERTYPE* pSoldier = NULL;
for ( int ubLoop = gTacticalStatus.Team[gbPlayerNum].bFirstID; ubLoop <= gTacticalStatus.Team[gbPlayerNum].bLastID; ++ubLoop )
{
pSoldier = MercPtrs[ubLoop];
if ( pSoldier && pSoldier->bVisible && pSoldier->usChatPartnerID != NOBODY && MercPtrs[pSoldier->usChatPartnerID]->bVisible )
{
INT16 sScreenX, sScreenY;
if ( fMercQuoteThisTime )
GetSoldierScreenPos( pSoldier, &sScreenX, &sScreenY );
else
GetSoldierScreenPos( MercPtrs[pSoldier->usChatPartnerID], &sScreenX, &sScreenY );
if ( gsVIEWPORT_START_X <= sScreenX &&
gsVIEWPORT_END_X >= sScreenX &&
gsVIEWPORT_WINDOW_START_Y <= sScreenY &&
gsVIEWPORT_WINDOW_END_Y >= sScreenY )
{
if ( fMercQuoteThisTime )
BeginChatQuote( pSoldier, sScreenX, sScreenY );
else
BeginChatQuote( MercPtrs[pSoldier->usChatPartnerID], sScreenX, sScreenY );
fMercQuoteThisTime = !fMercQuoteThisTime;
break;
}
}
}
}
}
}
// Flugente: offer the enemy the chance to surrender
void HandleSurrenderOffer( SOLDIERTYPE* pSoldier )
{
@@ -10694,7 +10764,21 @@ void HandleSurrenderOffer( SOLDIERTYPE* pSoldier )
// open a dialogue box and see wether we really want to offer this, or just talk
wcscpy( gzUserDefinedButton[0], TacticalStr[ PRISONER_DEMAND_SURRENDER_STR ] );
wcscpy( gzUserDefinedButton[1], TacticalStr[ PRISONER_OFFER_SURRENDER_STR ] );
wcscpy( gzUserDefinedButton[2], TacticalStr[ PRISONER_TALK_STR ] );
SOLDIERTYPE* pTargetSoldier = NULL;
if ( GetSoldier( &pTargetSoldier, prisonerdialoguetargetID ) &&
pTargetSoldier->bTeam == ENEMY_TEAM &&
pTargetSoldier->ubProfile == NO_PROFILE &&
pTargetSoldier->aiData.bAlertStatus < STATUS_RED &&
!pTargetSoldier->RecognizeAsCombatant( gusSelectedSoldier ) )
{
wcscpy( gzUserDefinedButton[2], TacticalStr[PRISONER_DISTRACT_STR] );
}
else
{
wcscpy( gzUserDefinedButton[2], TacticalStr[PRISONER_TALK_STR] );
}
wcscpy( gzUserDefinedButton[3], TacticalStr[ PRISONER_TALK_STR ] );
DoMessageBox( MSG_BOX_BASIC_MEDIUM_BUTTONS, TacticalStr[ PRISONER_OFFER_SURRENDER ], guiCurrentScreen, MSG_BOX_FLAG_GENERIC_FOUR_BUTTONS, PrisonerSurrenderMessageBoxCallBack, NULL );
}
+3
View File
@@ -357,6 +357,9 @@ extern UINT8 NumZombiesInSector();
// Flugente: offer the enemy the chance to surrender
void HandleSurrenderOffer( SOLDIERTYPE* pSoldier );
// Flugente: disguised mercs can distract enemies by talking to them. In order to display that, we sometimes display excerpts of their 'chats'
void CheckChatPartners();
// Flugente: order a team to drop gear, or pick it up
// setting fForce to TRUE allows dropping of gear in combat (used in auto-resolve instances)
void TeamDropAll(UINT8 bTeam, BOOLEAN fForce = FALSE);
+2
View File
@@ -923,6 +923,8 @@ void DeductPoints( SOLDIERTYPE *pSoldier, INT16 sAPCost, INT32 iBPCost, UINT8 ub
// if we are temporarily overt
if ( pSoldier->usSoldierFlagMask & SOLDIER_COVERT_TEMPORARY_OVERT && pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_COVERTOPS_TEMPORARYOVERT_APS] > 0 )
pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_COVERTOPS_TEMPORARYOVERT_APS] = max( 0, (INT16)(pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_COVERTOPS_TEMPORARYOVERT_APS] - sAPCost) );
pSoldier->StopChatting();
}
// in real time, there IS no AP cost, (only breath cost)
+11
View File
@@ -19968,6 +19968,17 @@ FLOAT SOLDIERTYPE::GetIntelGain()
return totalvalue;
}
void SOLDIERTYPE::StopChatting()
{
if ( this->usChatPartnerID != NOBODY )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[DISTRACT_STOP_STR], this->GetName(), MercPtrs[this->usChatPartnerID]->GetName() );
MercPtrs[this->usChatPartnerID]->usChatPartnerID = NOBODY;
this->usChatPartnerID = NOBODY;
}
}
INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
{
INT8 bBandaged; //,savedOurTurn;
+3 -1
View File
@@ -1506,7 +1506,7 @@ public:
//INT16 bUnusedINT16_4;
INT16 sDragCorpseID; // Flugente: id of corpse we are dragging
INT16 bUnusedINT16_5;
UINT16 usChatPartnerID; // Flugente: the id of another merc we are 'chatting' with
// Flugente: new variables for extra stats
INT16 bExtraStrength; // additional strength gained via power armor
@@ -1979,6 +1979,8 @@ public:
// Flugente: spy assignments
UINT8 GetUncoverRisk();
FLOAT GetIntelGain();
void StopChatting();
//////////////////////////////////////////////////////////////////////////////
}; // SOLDIERTYPE;