New Feature: dynamic dialogue is played when dynamic opinions are active. Mercs can comment on each others actions, and this can influence their opinions further. IMP character answers can even be chosen by the player.

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7297 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2014-06-27 22:12:29 +00:00
parent b083314318
commit 3a9cb5ecc3
52 changed files with 9062 additions and 5920 deletions
+1
View File
@@ -14,6 +14,7 @@
#include "Laptop.h"
#include "LaptopSave.h"
#include "email.h"
#include "DynamicDialogue.h"
Campaign_Stats gCampaignStats;
Incident_Stats gCurrentIncident; // we might save during an incident, thus we have to store the ongoing incident
+3 -3
View File
@@ -479,7 +479,7 @@ DropDownBase::SelectDropDownRegionCallBack(MOUSE_REGION * pRegion, INT32 iReason
else if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP)
{
UINT8 ubSelected = (UINT8)MSYS_GetRegionUserData( pRegion, 0 );
mSelectedEntry = min(ubSelected + mFirstShownEntry, max(0, mEntryVector.size() -1) );
mSelectedEntry = min(ubSelected + mFirstShownEntry, (UINT8)(max(0, mEntryVector.size() -1)) );
Destroy_Drop();
}
@@ -549,10 +549,10 @@ DropDownBase::SelectScrollAreaDropDownMovementCallBack(MOUSE_REGION * pRegion, I
}
else if( mFirstShownEntry + ubCityNum > mSelectedEntry )
{
mSelectedEntry = min( mFirstShownEntry + ubCityNum, max( 0, mEntryVector.size( ) - 1 ) );
mSelectedEntry = min( mFirstShownEntry + ubCityNum, (UINT8)(max( 0, mEntryVector.size( ) - 1 )) );
if ( ubCityNum == mNumDisplayedEntries - 1 )
mFirstShownEntry = min( mFirstShownEntry + 1, max( 0, mEntryVector.size( ) - 1 ) );
mFirstShownEntry = min( mFirstShownEntry + 1, (UINT8)(max( 0, mEntryVector.size( ) - 1 )) );
}
InvalidateRegion(pRegion->RegionTopLeftX, pRegion->RegionTopLeftY, pRegion->RegionBottomRightX, pRegion->RegionBottomRightY);
+14 -3
View File
@@ -16,7 +16,7 @@ void Display2Line2ShadowVertical( UINT16 usStartX, UINT16 usStartY, UINT16 EndX,
void Display2Line2ShadowHorizontal( UINT16 usStartX, UINT16 usStartY, UINT16 EndY, UINT16 usColor1, UINT16 usColor2 );
/*
* A simple class that takes coordiantes and colors.
* A simple class that takes coordinates and colors.
* It simply exists to provide these simple methods for other classes.
*/
class WidgetBase
@@ -28,9 +28,17 @@ public:
* X and Y-Coordinates define the upper left corner
*/
void SetX( UINT16 aVal ) { musStartX = aVal; }
UINT16 GetX( ) { return musStartX; }
virtual UINT16 GetX( ) { return musStartX; }
void SetY( UINT16 aVal ) { musStartY = aVal; }
UINT16 GetY( ) { return musStartY; }
virtual UINT16 GetY( ) { return musStartY; }
/*
* X and Y-Coordinates for text
*/
void SetX_Text( UINT16 aVal ) { musStartX_Text = aVal; }
virtual UINT16 GetX_Text( ) { return musStartX_Text; }
void SetY_Text( UINT16 aVal ) { musStartY_Text = aVal; }
virtual UINT16 GetY_Text( ) { return musStartY_Text; }
/*
* Color of boundary line
@@ -65,6 +73,9 @@ private:
UINT16 musStartX;
UINT16 musStartY;
UINT16 musStartX_Text;
UINT16 musStartY_Text;
UINT16 mColorLine; // color of boundary lines
UINT16 mColorLineShadow; // color of boundary line shadows
UINT16 mColorMarked; // color of marked entries
+685
View File
@@ -0,0 +1,685 @@
/**
* @file
* @author Flugente (bears-pit.com)
* @brief This file contains definitions of classes and functions used for dynamic dialogue
*/
#include "DynamicDialogueWidget.h"
#include "WCheck.h"
#include "renderworld.h"
#include "Font Control.h"
#include "Utilities.h"
#include "WordWrap.h"
#include "Soldier Profile.h"
#include "Cursors.h"
#include "random.h"
#include "faces.h"
extern FACETYPE *gpCurrentTalkingFace;
// whether we are showing the inventory pool graphic
extern BOOLEAN fShowMapInventoryPool;
extern void Display2Line2ShadowVertical( UINT16 usStartX, UINT16 usStartY, UINT16 EndX, UINT16 usColor1, UINT16 usColor2 );
extern void Display2Line2ShadowHorizontal( UINT16 usStartX, UINT16 usStartY, UINT16 EndY, UINT16 usColor1, UINT16 usColor2 );
#define MYBOX_NUMBER 10
#define MYBOX_FONT_DEF FONT12ARIAL
#define IMPDIALOGUECHOOSEBOX_BAR_Y_OFFSET 20
#define IMPDIALOGUECHOOSEBOX_BAR_MAXLENGTH 500
DDBox::DDBox( UINT8 aID )
: WidgetBase( )
{
// default settings
musHeight = 0;
musWidth = 0; // width of text field
swprintf( mText, L"" );
musCreationTime = musEndTime = GetJA2Clock( );
musID = aID;
mfInit = FALSE;
mfDisplayed = FALSE;
mfFaceImageExists = FALSE;
}
void
DDBox::Init( UINT16 sX, UINT16 sY )
{
SetX( sX );
SetY( sY );
SetX_Text( GetX( ) + MYBOX_FACE_OFFSET );
SetY_Text( GetY( ) );
musWidth = min( MYBOX_TEXT_MAXWIDTH, StringPixLength( mText, MYBOX_FONT_DEF ) );
musHeight = IanWrappedStringHeight( GetX_Text( ), GetY_Text( ) + 7, musWidth, 2, MYBOX_FONT_DEF, FONT_BLACK, mText, FONT_MCOLOR_BLACK, FALSE, 0 );
musFontHeight = GetFontHeight( MYBOX_FONT_DEF ); // does not work on init of static objects, as the fonts do not yet exist!
musEndTime = musCreationTime = GetJA2Clock( );
musFaceImage = 0;
mfInit = TRUE;
}
void
DDBox::Create( UINT16 sX, UINT16 sY )
{
Destroy( );
Init( sX, sY );
mfDisplayed = TRUE;
}
void
DDBox::Destroy( )
{
if ( !IsInit( ) )
return;
DeleteVideoObjectFromIndex( musFaceImage );
musFaceImage = 0;
mfInit = FALSE;
mfDisplayed = FALSE;
mfFaceImageExists = FALSE;
SetRenderFlags( RENDER_FLAG_FULL );
Refresh( );
RemoveDDBox( GetID( ) );
}
void
DDBox::Display( )
{
if ( !IsDisplayed( ) )
return;
// it is possible that we cannot instantly create the video object. Thus we try until we are sucessful
if ( !mfFaceImageExists )
{
VOBJECT_DESC VObjectDesc;
char sTemp[100];
// Load face file
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
// IMP faces are stored elsewhere
if ( gProfilesIMP[mEvent.usSpeaker].ProfilId == mEvent.usSpeaker )
{
sprintf( sTemp, "IMPFACES\\%02d.sti", gMercProfiles[mEvent.usSpeaker].ubFaceIndex );
}
else
{
sprintf( sTemp, "FACES\\%02d.sti", mEvent.usSpeaker );
}
FilenameForBPP( sTemp, VObjectDesc.ImageFile );
if ( AddVideoObject( &VObjectDesc, &musFaceImage ) )
mfFaceImageExists = TRUE;
}
if ( mfFaceImageExists )
{
HVOBJECT hPixHandle;
//Get the merc's face
if ( GetVideoObject( &hPixHandle, musFaceImage ) )
{
//if the merc is dead, shade the face red
if ( IsMercDead( mEvent.usSpeaker ) )
{
// if the merc is dead, shade the face red, (to signify that he is dead)
hPixHandle->pShades[0] = Create16BPPPaletteShaded( hPixHandle->pPaletteEntry, 255, 55, 55, TRUE );
//set the red pallete to the face
SetObjectHandleShade( musFaceImage, 0 );
}
//Get and display the mercs face
BltVideoObject( FRAME_BUFFER, hPixHandle, 0, GetX( ), GetY( ), VO_BLT_SRCTRANSPARENCY, NULL );
}
}
//Display the background
ColorFillVideoSurfaceArea( FRAME_BUFFER, GetX_Text( ), GetY( ), GetX_Text( ) + musWidth, GetY( ) + musFontHeight, Get16BPPColor( FROMRGB( 0, 0, 0 ) ) );
DrawTopEntry( );
SetRenderFlags( RENDER_FLAG_FULL );
}
void
DDBox::Refresh( )
{
// nothing to do if not initialized
if ( !IsInit( ) )
{
return;
}
// if still being displayed
else if ( IsDisplayed( ) )
{
// if not to be shown yet, hide
if ( musCreationTime > GetJA2Clock( ) )
{
;
}
// outdated -> destroy
else if ( musEndTime < GetJA2Clock( ) )
{
Destroy( );
}
else
{
Display( );
}
}
else
{
Destroy( );
}
}
UINT16
DDBox::GetY( )
{
UINT16 sY = WidgetBase::GetY( );
if ( mEvent.usSide == DOST_POSITION_LEFT && gpCurrentTalkingFace )
sY += 130;
return sY;
}
UINT16
DDBox::GetY_Text( )
{
UINT16 sY = WidgetBase::GetY_Text( );
if ( mEvent.usSide == DOST_POSITION_LEFT && gpCurrentTalkingFace )
sY += 130;
return sY;
}
void
DDBox::DrawTopEntry( )
{
//display the name in the list
ColorFillVideoSurfaceArea( FRAME_BUFFER, GetX_Text( ) - 4, GetY_Text( ) - 4, GetX_Text( ) + musWidth + 4, GetY_Text( ) + musHeight + 4, GetColorMarked( ) );
SetFontShadow( NO_SHADOW );
DisplayWrappedString( GetX_Text( ), GetY_Text( ) + 4, musWidth, 2, MYBOX_FONT_DEF, FONT_BLACK, mText, FONT_MCOLOR_BLACK, FALSE, 0 );
SetFontShadow( DEFAULT_SHADOW );
}
void
DDBox::ResetCreationTime( )
{
musCreationTime = GetJA2Clock( );
}
// the list of boxes
DDBox *gDDBoxList[MYBOX_NUMBER];
BOOLEAN
InitMyBoxes( )
{
// init the pop up box list
for ( UINT8 i = 0; i < MYBOX_NUMBER; ++i )
{
// set ptr to null
gDDBoxList[i] = NULL;
}
return TRUE;
}
DDBox*
GetDDBox( UINT8 aID )
{
// now find this box in the list
for ( UINT8 i = 0; i < MYBOX_NUMBER; ++i )
{
if ( gDDBoxList[i] != NULL && gDDBoxList[i]->GetID( ) == aID )
{
return gDDBoxList[i];
}
}
// create box
DDBox* gDDBox = new DDBox( aID );
if ( gDDBox )
{
// attempt to add box to list
for ( UINT8 i = 0; i < MYBOX_NUMBER; ++i )
{
if ( gDDBoxList[i] == NULL )
{
// found a spot, insert
gDDBoxList[i] = gDDBox;
return gDDBoxList[i];
}
}
}
return NULL;
}
BOOLEAN RemoveDDBox( UINT8 aID )
{
// now find this box in the list
for ( UINT8 i = 0; i < MYBOX_NUMBER; ++i )
{
if ( gDDBoxList[i] != NULL && gDDBoxList[i]->GetID( ) == aID )
{
gDDBoxList[i]->Destroy( );
MemFree( gDDBoxList[i] );
gDDBoxList[i] = NULL;
return TRUE;
}
}
return FALSE;
}
void RefreshBoxes( )
{
// if feature is not on, don't bother with this
if ( !gGameExternalOptions.fDynamicDialogue )
return;
static UINT32 lasttimenhere = GetJA2Clock( );
// dialogue should only happen in GAME_SCREEN or MAP_SCREEN, at other times it would be too distracting
// also halt dialogue if sector inventory is open
if ( guiCurrentScreen == GAME_SCREEN || guiCurrentScreen == MAP_SCREEN && !fShowMapInventoryPool )
{
// refresh all boxes, and while you're at it, check wether there are any
BOOLEAN fFound = FALSE;
for ( UINT8 i = 0; i < MYBOX_NUMBER; ++i )
{
if ( gDDBoxList[i] != NULL )
{
gDDBoxList[i]->Refresh( );
fFound = TRUE;
}
}
if ( IMPDialogueChooseBox_Static::getInstance( ).IsDisplayed( ) )
{
IMPDialogueChooseBox_Static::getInstance( ).Refresh( );
fFound = TRUE;
}
// if no box is active, we are free to start another dialogue
if ( !fFound )
HandleDynamicOpinionSpeechEvents( );
else
{
// boxes are active, thus we have to refresh them
fMapPanelDirty = TRUE;
}
}
else
{
// Our dynamic dialogue boxes are destroyed as time progresses. As we do not display them at the moment, we have to update their creation and end time.
// As a result, no time will be lost for our dialogues if we are in a different screen
UINT32 timepassednotdisplaying = max( 0, GetJA2Clock( ) - lasttimenhere );
if ( timepassednotdisplaying )
DelayBoxDestructionBy( timepassednotdisplaying );
}
lasttimenhere = GetJA2Clock( );
}
void DelayBoxDestruction( UINT32 aVal )
{
// now find this box in the list
for ( UINT8 i = 0; i < MYBOX_NUMBER; ++i )
{
if ( gDDBoxList[i] != NULL && gDDBoxList[i]->IsDisplayed( ) )
{
gDDBoxList[i]->SetEndTime( aVal );
}
}
}
void DelayBoxDestructionBy( UINT32 aVal )
{
// now find this box in the list
for ( UINT8 i = 0; i < MYBOX_NUMBER; ++i )
{
if ( gDDBoxList[i] != NULL && gDDBoxList[i]->IsDisplayed( ) )
{
gDDBoxList[i]->SetStartTime( gDDBoxList[i]->GetStartTime( ) + aVal );
gDDBoxList[i]->SetEndTime( gDDBoxList[i]->GetEndTime( ) + aVal );
}
}
if ( IMPDialogueChooseBox_Static::getInstance( ).IsDisplayed( ) )
{
IMPDialogueChooseBox_Static::getInstance( ).SetStartTime( IMPDialogueChooseBox_Static::getInstance( ).GetStartTime( ) + aVal );
IMPDialogueChooseBox_Static::getInstance( ).SetEndTime( IMPDialogueChooseBox_Static::getInstance( ).GetEndTime( ) + aVal );
}
}
IMPDialogueChooseBox::IMPDialogueChooseBox( )
{
// default settings
musWidth = 0; // width of text field
mEntryVector.clear( );
swprintf( mText, L"" );
mSelectedEntry = 0;
for ( UINT8 i = 0; i < DOST_CHOICE_MAX; ++i )
mChoiceRegionDefined[i] = FALSE;
musCreationTime = musEndTime = GetJA2Clock( );
mfInit = FALSE;
mfDisplayed = FALSE;
}
void
IMPDialogueChooseBox::Init( UINT16 sX, UINT16 sY )
{
SetX( sX );
SetY( sY );
SetX_Text( GetX( ) + MYBOX_FACE_OFFSET );
SetY_Text( GetY( ) );
mSelectedEntry = 0;
musWidth = 0;
UINT8 size = mEntryVector.size( );
for ( UINT8 i = 0; i < size; ++i )
{
musWidth = max( musWidth, StringPixLength( mEntryVector[i].second, MYBOX_FONT_DEF ) );
}
musFontHeight = GetFontHeight( MYBOX_FONT_DEF ); // does not work on init of static objects, as the fonts do not yet exist!
musCreationTime = GetJA2Clock( );
musEndTime = musCreationTime;
mfInit = TRUE;
}
void
IMPDialogueChooseBox::Create( UINT16 sX, UINT16 sY )
{
Destroy( );
Init( sX, sY );
sY += IMPDIALOGUECHOOSEBOX_BAR_Y_OFFSET;
UINT8 size = mEntryVector.size( );
for ( UINT8 i = 0; i < size; ++i )
{
if ( !mChoiceRegionDefined[i] )
{
MSYS_DefineRegion( &mChoiceRegion[i], GetX( ) - 4, sY, GetX( ) + musWidth + 4, sY + musFontHeight, MSYS_PRIORITY_HIGH,
CURSOR_WWW, MSYS_NO_CALLBACK, CallBackWrapper( (void*) this, DROPDOWN_REGION, &IMPDialogueChooseBox::Dummyfunc ) );
MSYS_AddRegion( &mChoiceRegion[i] );
MSYS_SetRegionUserData( &mChoiceRegion[i], 0, i );
mChoiceRegionDefined[i] = TRUE;
}
sY += musFontHeight + 2;
}
mfDisplayed = TRUE;
}
void
IMPDialogueChooseBox::Destroy( )
{
if ( !IsInit( ) )
return;
for ( UINT8 i = 0; i < DOST_CHOICE_MAX; ++i )
{
if ( mChoiceRegionDefined[i] )
{
MSYS_RemoveRegion( &mChoiceRegion[i] );
mChoiceRegionDefined[i] = FALSE;
}
}
mfInit = FALSE;
mfDisplayed = FALSE;
SetRenderFlags( RENDER_FLAG_FULL );
Refresh( );
}
void
IMPDialogueChooseBox::Display( )
{
if ( !IsDisplayed( ) )
return;
// we draw a line that shwos us how much time we have for the decision
UINT32 totaltime = max( 0, musEndTime - musCreationTime );
if ( totaltime )
{
UINT32 timeleft = musEndTime - GetJA2Clock( );
FLOAT factor = (FLOAT)timeleft / (FLOAT)totaltime;
UINT32 maxwidth = min( IMPDIALOGUECHOOSEBOX_BAR_MAXLENGTH, SCREEN_WIDTH / 2 );
UINT16 colour = Get16BPPColor( FROMRGB( 255 * (1 - factor), 255 * factor, 0 ) );
UINT16 colourshadow = Get16BPPColor( FROMRGB( 127 * (1 - factor), 127 * factor, 0 ) );
Display2Line2ShadowHorizontal( GetX_Text( ) + maxwidth / 2 - factor * maxwidth / 2, GetY( ), GetX_Text( ) + maxwidth / 2 + factor * maxwidth / 2, colour, colourshadow );
}
DrawTopEntry( );
SetRenderFlags( RENDER_FLAG_FULL );
}
void
IMPDialogueChooseBox::Refresh( )
{
// nothing to do if not initialized
if ( !IsInit( ) )
{
return;
}
// if still being displayed
else if ( IsDisplayed( ) )
{
// if not to be shown yet, hide
if ( musCreationTime > GetJA2Clock( ) )
{
;
}
// outdated -> destroy
else if ( musEndTime < GetJA2Clock( ) )
{
TimeOut( );
Destroy( );
}
else
{
Display( );
}
}
else
{
Destroy( );
}
}
void
IMPDialogueChooseBox::DrawTopEntry( )
{
// make sure we don't get bogus values
mSelectedEntry = min( mSelectedEntry, mEntryVector.size( ) - 1 );
UINT16 sY = GetY( ) + IMPDIALOGUECHOOSEBOX_BAR_Y_OFFSET;
UINT8 cnt = 0;
std::vector<std::pair<INT16, STR16> >::iterator itend = mEntryVector.end( );
for ( std::vector<std::pair<INT16, STR16> >::iterator it = mEntryVector.begin( ); it != itend; ++it )
{
//display the name in the list
ColorFillVideoSurfaceArea( FRAME_BUFFER, GetX( ) - 4, sY, GetX( ) + musWidth + 4, sY + musFontHeight, cnt == mSelectedEntry ? GetColorHighLight( ) : GetColorMarked( ) );
SetFontShadow( NO_SHADOW );
DrawTextToScreen( (*it).second, GetX( ), sY, 0, MYBOX_FONT_DEF, cnt == mSelectedEntry ? FONT_DKGREEN : FONT_BLACK, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED );
SetFontShadow( DEFAULT_SHADOW );
sY += musFontHeight + 2;
++cnt;
}
}
void
IMPDialogueChooseBox::SelectDropDownRegionCallBack( MOUSE_REGION * pRegion, INT32 iReason )
{
if ( iReason & MSYS_CALLBACK_REASON_INIT )
{
}
else if ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
mSelectedEntry = (UINT8)MSYS_GetRegionUserData( pRegion, 0 );
}
}
void
IMPDialogueChooseBox::ResetCreationTime( )
{
musCreationTime = GetJA2Clock( );
}
void
IMPDialogueChooseBox::TimeOut( )
{
// if we are destroyed, we set up dialogues according to the players choices
RemoveDDBox( mEvent.usSpeaker );
DynamicOpinionSpeechEvent event = mEvent;
switch ( mSelectedEntry )
{
case DOST_CHOICE_NOTHING:
event.ubEventType = DOST_INTERJECTOR_NOTHING;
break;
// if we side with the victim or the cause, we either support them or take a stand against the other
// for now, the choice is random
case DOST_CHOICE_SIDEWITH_VICTIM:
if ( Random( 2 ) )
event.ubEventType = DOST_INTERJECTOR_TO_VICTIM_AGREE;
else
event.ubEventType = DOST_INTERJECTOR_TO_CAUSE_DENY;
event.usSide = DOST_POSITION_LEFT;
break;
case DOST_CHOICE_SIDEWITH_CAUSE:
if ( Random( 2 ) )
event.ubEventType = DOST_INTERJECTOR_TO_CAUSE_AGREE;
else
event.ubEventType = DOST_INTERJECTOR_TO_VICTIM_DENY;
event.usSide = DOST_POSITION_RIGHT;
break;
case DOST_CHOICE_REASON:
event.ubEventType = DOST_INTERJECTOR_SOLVE_REASON;
break;
case DOST_CHOICE_AGGRESSIVE:
event.ubEventType = DOST_INTERJECTOR_SOLVE_AGGRESSIVE;
break;
}
event.usQueueNumber++;
event.usStarttime = GetJA2Clock( );
event.usNumonside = (UINT8)GetSidePosition( event.usSide );
AddDynamicOpinionEvent_Continue( event );
}
void* IMPDialogueChooseBox_Static::mpSelf = NULL;
// are there still dynamic dialogue boxes active? We use this to check wether we can start new dialogue
BOOLEAN DynamicDialogueBoxesActive( )
{
// now find this box in the list
for ( UINT8 i = 0; i < MYBOX_NUMBER; ++i )
{
if ( gDDBoxList[i] != NULL )
return TRUE;
}
if ( IMPDialogueChooseBox_Static::getInstance( ).IsInit( ) )
return TRUE;
return FALSE;
}
// used fo example when we load a game - dialogue has to start anew, so all boxes must be wiped
void DestroyAllDynamicDialogueBoxes( )
{
// now find this box in the list
for ( UINT8 i = 0; i < MYBOX_NUMBER; ++i )
{
if ( gDDBoxList[i] != NULL )
{
gDDBoxList[i]->Destroy( );
MemFree( gDDBoxList[i] );
gDDBoxList[i] = NULL;
}
}
IMPDialogueChooseBox_Static::getInstance( ).Destroy( );
}
+322
View File
@@ -0,0 +1,322 @@
#ifndef __DYNAMICDIALOGUEWIDGET_H
#define __DYNAMICDIALOGUEWIDGET_H
/**
* @file
* @author Flugente (bears-pit.com)
* @brief This file contains declarations of classes and functions used for dynamic dialogue
*/
// Flugente: stuff
#include "Morale.h"
#include "DropDown.h"
#include "DynamicDialogue.h"
#define MYBOX_TEXT_MAXWIDTH 200
#define MYBOX_FACE_OFFSET 53
/*
* A class for dynamic dialogue boxes
* These boxes consist of a box with a merc's face in it, and text right next to it
*/
class DDBox : public WidgetBase
{
public:
DDBox( UINT8 aID );
/*
* Create a Dropdown with upper left coordinates
*/
void Create( UINT16 sX, UINT16 sY );
/*
* Destroy Dropdown, for example once a website isn't displayed anymore
*/
void Destroy( );
/*
* Display DropDownBase. Use this when refreshing
*/
void Display( );
void Refresh( );
// we need to redo these functions, as the position can change dynamically
virtual UINT16 GetY( );
virtual UINT16 GetY_Text( );
/*
* Set help text decribing what can be selected
*/
void SetText( STR16 aText )
{
swprintf( mText, L"" );
wcscat( mText, aText );
}
/*
* Get width of entire DropDownBase
*/
UINT16 GetTotalWidth( ) { return musWidth; }
/*
* Get right x coordinate
*/
UINT16 GetLastX( ) { return GetX( ) + GetTotalWidth( ); }
BOOLEAN IsInit( ) { return mfInit; }
/*
* Are we displayed?
*/
BOOLEAN IsDisplayed( ) { return mfDisplayed; }
void SetEndTime( UINT32 aVal ) { musEndTime = aVal; }
UINT32 GetEndTime( ) { return musEndTime; }
void SetStartTime( UINT32 aVal ) { musCreationTime = aVal; }
UINT32 GetStartTime( ) { return musCreationTime; }
UINT8 GetID( ) { return musID; }
void SetEvent( DynamicOpinionSpeechEvent& aEvent ) { mEvent = aEvent; }
void ResetCreationTime( );
private:
// declare but don't define
DDBox( DDBox const& );
void operator=(DDBox const&);
/*
* Initialise variables. Called after each creationm which allows moving a dropdown
*/
void Init( UINT16 sX, UINT16 sY );
void DrawTopEntry( );
private:
UINT16 musHeight;
UINT16 musWidth;
UINT16 musFontHeight;
BOOLEAN mfInit;
BOOLEAN mfDisplayed;
BOOLEAN mfFaceImageExists;
CHAR16 mText[500];
UINT32 musCreationTime;
UINT32 musEndTime;
UINT8 musID;
UINT32 musFaceImage;
DynamicOpinionSpeechEvent mEvent;
};
BOOLEAN InitMyBoxes( );
DDBox* GetDDBox( UINT8 aID );
BOOLEAN RemoveDDBox( UINT8 aID );
void RefreshBoxes( );
void DelayBoxDestruction( UINT32 aVal );
void DelayBoxDestructionBy( UINT32 aVal );
class IMPDialogueChooseBox : public WidgetBase
{
public:
IMPDialogueChooseBox( );
/*
* Create a Dropdown with upper left coordinates
*/
void Create( UINT16 sX, UINT16 sY );
/*
* Destroy Dropdown, for example once a website isn't displayed anymore
*/
void Destroy( );
/*
* Display DropDownBase. Use this when refreshing
*/
void Display( );
void Refresh( );
// internal callback types
enum {
DROPDOWN_REGION,
};
/*
* Set the content of a dropdown. Each entry consists of an INT16 key, by which you can later identify which entry was selected, and a STR16 that will be displayed.
* There can be multiple instances of the same key or name.
*/
void SetEntries( std::vector<std::pair<INT16, STR16> >& arEntryVec ) { mEntryVector = arEntryVec; }
/*
* Set help text decribing what can be selected
*/
void SetText( STR16 aText )
{
swprintf( mText, L"" );
wcscat( mText, aText );
}
/*
* Set help text decribing what can be selected
*/
void SetHelpText( STR16 aText ) { swprintf( mHelpText, L"" ); wcscat( mHelpText, aText ); }
/*
* Get key of selected entry
*/
INT16 GetSelectedEntryKey( ) { return mEntryVector[mSelectedEntry].first; }
/*
* Get width of entire DropDownBase
*/
UINT16 GetTotalWidth( ) { return musWidth; }
/*
* Get right x coordinate
*/
UINT16 GetLastX( ) { return GetX( ) + GetTotalWidth( ); }
BOOLEAN IsInit( ) { return mfInit; }
/*
* Are we displayed?
*/
BOOLEAN IsDisplayed( ) { return mfDisplayed; }
/*
* Do we have data to display?
*/
BOOLEAN HasEntries( ) { return !mEntryVector.empty( ); }
void SelectDropDownRegionCallBack( MOUSE_REGION * pRegion, INT32 iReason );
/*
* This function is implemented again in DropDownTemplate
*/
virtual MOUSE_CALLBACK CallBackWrapper( void* pt2Object, UINT8 arg, void( *pt2Function )(MOUSE_REGION * pRegion, INT32 iReason) ) {
return Dummyfunc;
}
void SetEndTime( UINT32 aVal ) { musEndTime = aVal; }
UINT32 GetEndTime( ) { return musEndTime; }
void SetStartTime( UINT32 aVal ) { musCreationTime = aVal; }
UINT32 GetStartTime( ) { return musCreationTime; }
void SetEvent( DynamicOpinionSpeechEvent& aEvent ) { mEvent = aEvent; }
void ResetCreationTime( );
UINT32 GetTimeLeft( ) { return musEndTime - musCreationTime; }
private:
// declare but don't define
IMPDialogueChooseBox( IMPDialogueChooseBox const& );
void operator=(IMPDialogueChooseBox const&);
/*
* Initialise variables. Called after each creationm which allows moving a dropdown
*/
void Init( UINT16 sX, UINT16 sY );
/*
* This dummy is needed internally and does nothing when called
*/
static void Dummyfunc( MOUSE_REGION * pRegion, INT32 iReason ) {}
/*
* Stuff to do once the time is up
*/
void TimeOut( );
void DrawTopEntry( );
private:
UINT16 musHeight;
UINT16 musWidth;
UINT16 musFontHeight;
BOOLEAN mfInit;
BOOLEAN mfDisplayed;
BOOLEAN mfMouseRegionsCreated;
// a mouse region for every possible choice
MOUSE_REGION mChoiceRegion[DOST_CHOICE_MAX];
BOOLEAN mChoiceRegionDefined[DOST_CHOICE_MAX];
std::vector<std::pair<INT16, STR16> > mEntryVector;
CHAR16 mHelpText[200];
UINT8 mSelectedEntry; // keeps track of the currently selected city
CHAR16 mText[500];
UINT32 musCreationTime;
UINT32 musEndTime;
DynamicOpinionSpeechEvent mEvent;
};
class IMPDialogueChooseBox_Static : public IMPDialogueChooseBox
{
public:
static IMPDialogueChooseBox_Static& getInstance( )
{
static IMPDialogueChooseBox_Static instance; // Guaranteed to be destroyed.
// Instantiated on first use.
return instance;
}
static void SelectRegionDropDown_DropDown( MOUSE_REGION * pRegion, INT32 iReason ) { return static_cast<IMPDialogueChooseBox*>(mpSelf)->SelectDropDownRegionCallBack( pRegion, iReason ); }
MOUSE_CALLBACK
CallBackWrapper( void* pt2Object, UINT8 arg, void( *pt2Function )(MOUSE_REGION * pRegion, INT32 iReason) )
{
mpSelf = pt2Object;
switch ( arg )
{
case DROPDOWN_REGION:
return &SelectRegionDropDown_DropDown;
break;
}
return *pt2Function;
}
private:
static void* mpSelf;
private:
IMPDialogueChooseBox_Static( ) {}; // private constructor, so we cannot create more instances
// declare but don't define
IMPDialogueChooseBox_Static( IMPDialogueChooseBox_Static const& );
void operator=(IMPDialogueChooseBox_Static const&);
};
// are there still dynamic dialogue boxes active? We use this to check wether we can start new dialogue
BOOLEAN DynamicDialogueBoxesActive( );
// used fo example when we load a game - dialogue has to start anew, so all boxes must be wiped
void DestroyAllDynamicDialogueBoxes( );
#endif
+8
View File
@@ -442,6 +442,10 @@
RelativePath=".\DropDown.h"
>
</File>
<File
RelativePath=".\DynamicDialogueWidget.h"
>
</File>
<File
RelativePath=".\email.h"
>
@@ -768,6 +772,10 @@
RelativePath=".\DropDown.cpp"
>
</File>
<File
RelativePath=".\DynamicDialogueWidget.cpp"
>
</File>
<File
RelativePath=".\email.cpp"
>
+8
View File
@@ -442,6 +442,10 @@
RelativePath="DropDown.h"
>
</File>
<File
RelativePath="DynamicDialogueWidget.h"
>
</File>
<File
RelativePath="email.h"
>
@@ -758,6 +762,10 @@
RelativePath="DropDown.cpp"
>
</File>
<File
RelativePath="DynamicDialogueWidget.cpp"
>
</File>
<File
RelativePath="email.cpp"
>
+2
View File
@@ -49,6 +49,7 @@
<ClInclude Include="CampaignStats.h" />
<ClInclude Include="CharProfile.h" />
<ClInclude Include="DropDown.h" />
<ClInclude Include="DynamicDialogueWidget.h" />
<ClInclude Include="email.h" />
<ClInclude Include="Encyclopedia_Data_new.h" />
<ClInclude Include="Encyclopedia_new.h" />
@@ -131,6 +132,7 @@
<ClCompile Include="CampaignStats.cpp" />
<ClCompile Include="CharProfile.cpp" />
<ClCompile Include="DropDown.cpp" />
<ClInclude Include="DynamicDialogueWidget.cpp" />
<ClCompile Include="email.cpp" />
<ClCompile Include="Encyclopedia_Data_new.cpp" />
<ClCompile Include="Encyclopedia_new.cpp" />
+2
View File
@@ -49,6 +49,7 @@
<ClInclude Include="CampaignStats.h" />
<ClInclude Include="CharProfile.h" />
<ClInclude Include="DropDown.h" />
<ClInclude Include="DynamicDialogueWidget.h" />
<ClInclude Include="email.h" />
<ClInclude Include="Encyclopedia_Data_new.h" />
<ClInclude Include="Encyclopedia_new.h" />
@@ -131,6 +132,7 @@
<ClCompile Include="CampaignStats.cpp" />
<ClCompile Include="CharProfile.cpp" />
<ClCompile Include="DropDown.cpp" />
<ClCompile Include="DynamicDialogueWidget.cpp" />
<ClCompile Include="email.cpp" />
<ClCompile Include="Encyclopedia_Data_new.cpp" />
<ClCompile Include="Encyclopedia_new.cpp" />
+6
View File
@@ -252,6 +252,9 @@
<ClInclude Include="merccompare.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DynamicDialogueWidget.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="aim.cpp">
@@ -515,5 +518,8 @@
<ClCompile Include="merccompare.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DynamicDialogueWidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
+2
View File
@@ -21,6 +21,8 @@
// HEADROCK HAM 3.6: Militia upkeep
#include "Town Militia.h"
#include "CampaignStats.h" // added by Flugente
#include "DynamicDialogue.h" // added by Flugente
#endif
// the global defines
+248 -330
View File
File diff suppressed because it is too large Load Diff
+29 -8
View File
@@ -26,6 +26,7 @@
#include "DropDown.h"
#include "Overhead.h"
#include "Map Screen Interface.h"
#include "DynamicDialogue.h" // added by Flugente
#endif
@@ -343,14 +344,13 @@ void RenderMercCompareCustomers( )
// choose 3 random customer quotes out of the pool of all quotes
std::set<UINT8> quoteset;
//while ( quoteset.size( ) < min( 3, TEXT_MERCCOMPARE_CUSTOMERSTATEMENTS ) )
//quoteset.insert( Random( TEXT_MERCCOMPARE_CUSTOMERSTATEMENTS ) );
// showoff hack
quoteset.insert( 0 );
quoteset.insert( 1 );
quoteset.insert( 2 );
UINT8 safetycounter = 0;
while ( quoteset.size( ) < min( 3, TEXT_MERCCOMPARE_CUSTOMERSTATEMENTS ) && safetycounter < 30 )
{
quoteset.insert( Random( TEXT_MERCCOMPARE_CUSTOMERSTATEMENTS ) );
++safetycounter;
}
std::set<UINT8>::iterator itend = quoteset.end();
for ( std::set<UINT8>::iterator it = quoteset.begin(); it != itend; ++it )
{
@@ -933,6 +933,27 @@ BOOLEAN DisplayMercData( UINT8 usProfileA, UINT8 usProfileB )
}
}
// long-term memory
val = gMercProfiles[usProfileA].sDynamicOpinionLongTerm[usProfileB];
if ( val )
{
swprintf( sText, L"Past grievances" );
DisplayWrappedString( usPosX, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
swprintf( sText, L"%d", val );
usPosY += DisplayWrappedString( usPosX + MCA_NUMBEROFFSET, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, (val > 0) ? FONT_MCOLOR_LTGREEN : (val < 0) ? FONT_MCOLOR_LTRED : MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
}
val = gMercProfiles[usProfileB].sDynamicOpinionLongTerm[usProfileA];
if ( val )
{
swprintf( sText, L"Past grievances" );
DisplayWrappedString( usPosX + MCA_SIDEOFFSET, usPosY2, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
swprintf( sText, L"%d", val );
usPosY2 += DisplayWrappedString( usPosX + MCA_SIDEOFFSET + MCA_NUMBEROFFSET, usPosY2, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, (val > 0) ? FONT_MCOLOR_LTGREEN : (val < 0) ? FONT_MCOLOR_LTRED : MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
}
// draw the final verdict
val = SoldierRelation( pSoldierA, pSoldierB );