mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
- bugfix: Multiple IMPs with same voice causes wrong data and CTDs. Now it is impossible to have multiple IMPs with the same voice. No more invalid IMP data with multiple imps (hopefully) ;) - You can have a maximum number of 6 imps (3 women and 3 men). All have different voices - If an IMP is cloned (90210, nickname) an unused voice is set. So we have correct data - Prevent the user from selecting used voices in the IMP Voice selection screen git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@535 3b4a5df2-a311-0410-b5c6-a8a6f20db521
930 lines
24 KiB
C++
930 lines
24 KiB
C++
#ifdef PRECOMPILEDHEADERS
|
|
#include "Laptop All.h"
|
|
#else
|
|
#include "CharProfile.h"
|
|
#include "IMP MainPage.h"
|
|
#include "IMP HomePage.h"
|
|
#include "IMPVideoObjects.h"
|
|
#include "Utilities.h"
|
|
#include "WCheck.h"
|
|
#include "Debug.h"
|
|
#include "WordWrap.h"
|
|
#include "Render Dirty.h"
|
|
#include "Encrypted File.h"
|
|
#include "cursors.h"
|
|
#include "laptop.h"
|
|
#include "IMP Compile Character.h"
|
|
#include "soldier profile type.h"
|
|
#include "IMP Text System.h"
|
|
#include "IMP Confirm.h"
|
|
#include "finances.h"
|
|
#include "Soldier Profile.h"
|
|
#include "Soldier Profile Type.h"
|
|
#include "Soldier Control.h"
|
|
#include "IMP Portraits.h"
|
|
#include "IMP Voices.h"
|
|
#include "Overhead.h"
|
|
#include "finances.h"
|
|
#include "history.h"
|
|
#include "Game Clock.h"
|
|
#include "email.h"
|
|
#include "Game Event Hook.h"
|
|
#include "LaptopSave.h"
|
|
#include "strategic.h"
|
|
#endif
|
|
|
|
#define IMP_FILENAME_SUFFIX ".dat"
|
|
|
|
IMP_ITEM_CHOICE_TYPE gIMPItemChoices[MAX_IMP_ITEM_TYPES];
|
|
|
|
void GiveIMPRandomItems( MERCPROFILESTRUCT *pProfile, UINT8 typeIndex );
|
|
void GiveIMPItems( MERCPROFILESTRUCT *pProfile, INT8 abilityValue, UINT8 typeIndex );
|
|
|
|
UINT32 giIMPConfirmButton[ 2 ];
|
|
UINT32 giIMPConfirmButtonImage[ 2 ];
|
|
BOOLEAN fNoAlreadySelected = FALSE;
|
|
UINT16 uiEyeXPositions[ ]={
|
|
8,
|
|
9,
|
|
8,
|
|
6,
|
|
13,
|
|
11,
|
|
8,
|
|
8,
|
|
4, //208
|
|
5, //209
|
|
7,
|
|
5, //211
|
|
7,
|
|
11,
|
|
8, //214
|
|
5,
|
|
};
|
|
|
|
UINT16 uiEyeYPositions[ ]=
|
|
{
|
|
5,
|
|
4,
|
|
5,
|
|
6,
|
|
5,
|
|
5,
|
|
4,
|
|
4,
|
|
4, //208
|
|
5,
|
|
5, //210
|
|
7,
|
|
6, //212
|
|
5,
|
|
5, //214
|
|
6,
|
|
};
|
|
|
|
UINT16 uiMouthXPositions[]=
|
|
{
|
|
8,
|
|
9,
|
|
7,
|
|
7,
|
|
11,
|
|
10,
|
|
8,
|
|
8,
|
|
5, //208
|
|
6,
|
|
7, //210
|
|
6,
|
|
7, //212
|
|
9,
|
|
7, //214
|
|
5,
|
|
};
|
|
|
|
UINT16 uiMouthYPositions[]={
|
|
21,
|
|
23,
|
|
24,
|
|
25,
|
|
23,
|
|
24,
|
|
24,
|
|
24,
|
|
25, //208
|
|
24,
|
|
24, //210
|
|
26,
|
|
24, //212
|
|
23,
|
|
24, //214
|
|
26,
|
|
};
|
|
|
|
BOOLEAN fLoadingCharacterForPreviousImpProfile = FALSE;
|
|
|
|
void CreateConfirmButtons( void );
|
|
void DestroyConfirmButtons( void );
|
|
void GiveItemsToPC( UINT8 ubProfileId );
|
|
void MakeProfileInvItemAnySlot(MERCPROFILESTRUCT *pProfile, UINT16 usItem, UINT8 ubStatus, UINT8 ubHowMany);
|
|
void MakeProfileInvItemThisSlot(MERCPROFILESTRUCT *pProfile, UINT32 uiPos, UINT16 usItem, UINT8 ubStatus, UINT8 ubHowMany);
|
|
INT32 FirstFreeBigEnoughPocket(MERCPROFILESTRUCT *pProfile, UINT16 usItem);
|
|
|
|
// callbacks
|
|
void BtnIMPConfirmNo( GUI_BUTTON *btn,INT32 reason );
|
|
void BtnIMPConfirmYes( GUI_BUTTON *btn,INT32 reason );
|
|
|
|
|
|
void EnterIMPConfirm( void )
|
|
{
|
|
// create buttons
|
|
CreateConfirmButtons( );
|
|
return;
|
|
}
|
|
|
|
void RenderIMPConfirm( void )
|
|
{
|
|
|
|
// the background
|
|
RenderProfileBackGround( );
|
|
|
|
// indent
|
|
RenderAvgMercIndentFrame(90, 40 );
|
|
|
|
// highlight answer
|
|
PrintImpText( );
|
|
|
|
return;
|
|
}
|
|
|
|
void ExitIMPConfirm( void )
|
|
{
|
|
|
|
// destroy buttons
|
|
DestroyConfirmButtons( );
|
|
return;
|
|
}
|
|
|
|
void HandleIMPConfirm( void )
|
|
{
|
|
return;
|
|
}
|
|
|
|
void CreateConfirmButtons( void )
|
|
{
|
|
// create buttons for confirm screen
|
|
|
|
giIMPConfirmButtonImage[0]= LoadButtonImage( "LAPTOP\\button_2.sti" ,-1,0,-1,1,-1 );
|
|
giIMPConfirmButton[0] = CreateIconAndTextButton( giIMPConfirmButtonImage[0], pImpButtonText[ 16 ], FONT12ARIAL,
|
|
FONT_WHITE, DEFAULT_SHADOW,
|
|
FONT_WHITE, DEFAULT_SHADOW,
|
|
TEXT_CJUSTIFIED,
|
|
LAPTOP_SCREEN_UL_X + ( 136 ), LAPTOP_SCREEN_WEB_UL_Y + ( 254 ), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
|
|
BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnIMPConfirmYes);
|
|
|
|
giIMPConfirmButtonImage[1]= LoadButtonImage( "LAPTOP\\button_2.sti" ,-1,0,-1,1,-1 );
|
|
giIMPConfirmButton[1] = CreateIconAndTextButton( giIMPConfirmButtonImage[ 1 ], pImpButtonText[ 17 ], FONT12ARIAL,
|
|
FONT_WHITE, DEFAULT_SHADOW,
|
|
FONT_WHITE, DEFAULT_SHADOW,
|
|
TEXT_CJUSTIFIED,
|
|
LAPTOP_SCREEN_UL_X + ( 136 ), LAPTOP_SCREEN_WEB_UL_Y + ( 314 ), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
|
|
BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnIMPConfirmNo);
|
|
|
|
SetButtonCursor(giIMPConfirmButton[ 0 ], CURSOR_WWW);
|
|
SetButtonCursor(giIMPConfirmButton[ 1 ], CURSOR_WWW);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void DestroyConfirmButtons( void )
|
|
{
|
|
// destroy buttons for confirm screen
|
|
|
|
RemoveButton(giIMPConfirmButton[ 0 ] );
|
|
UnloadButtonImage(giIMPConfirmButtonImage[ 0 ] );
|
|
|
|
|
|
RemoveButton(giIMPConfirmButton[ 1 ] );
|
|
UnloadButtonImage(giIMPConfirmButtonImage[ 1 ] );
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN AddCharacterToPlayersTeam( void )
|
|
{
|
|
|
|
MERC_HIRE_STRUCT HireMercStruct;
|
|
|
|
|
|
// last minute chage to make sure merc with right facehas not only the right body but body specific skills...
|
|
// ie..small mercs have martial arts..but big guys and women don't don't
|
|
|
|
HandleMercStatsForChangesInFace( );
|
|
|
|
memset(&HireMercStruct, 0, sizeof(MERC_HIRE_STRUCT));
|
|
|
|
// WANNE NEW: Any changes here. I don't think so
|
|
HireMercStruct.ubProfileID = ( UINT8 )( PLAYER_GENERATED_CHARACTER_ID + LaptopSaveInfo.iVoiceId ) ;
|
|
|
|
if( fLoadingCharacterForPreviousImpProfile == FALSE )
|
|
{
|
|
// give them items
|
|
GiveItemsToPC( HireMercStruct.ubProfileID );
|
|
}
|
|
|
|
|
|
HireMercStruct.sSectorX = gsMercArriveSectorX;
|
|
HireMercStruct.sSectorY = gsMercArriveSectorY;
|
|
HireMercStruct.fUseLandingZoneForArrival = TRUE;
|
|
|
|
HireMercStruct.fCopyProfileItemsOver = TRUE;
|
|
|
|
// indefinite contract length
|
|
HireMercStruct.iTotalContractLength = -1;
|
|
|
|
HireMercStruct.ubInsertionCode = INSERTION_CODE_ARRIVING_GAME;
|
|
HireMercStruct.uiTimeTillMercArrives = GetMercArrivalTimeOfDay( );
|
|
|
|
SetProfileFaceData( HireMercStruct.ubProfileID , ( UINT8 ) ( 200 + iPortraitNumber ), uiEyeXPositions[ iPortraitNumber ], uiEyeYPositions[ iPortraitNumber ], uiMouthXPositions[ iPortraitNumber ], uiMouthYPositions[ iPortraitNumber ] );
|
|
|
|
//if we succesfully hired the merc
|
|
if( !HireMerc( &HireMercStruct ) )
|
|
{
|
|
return(FALSE);
|
|
}
|
|
else
|
|
{
|
|
return ( TRUE );
|
|
}
|
|
}
|
|
|
|
|
|
void BtnIMPConfirmYes(GUI_BUTTON *btn,INT32 reason)
|
|
{
|
|
|
|
// btn callback for IMP Homepage About US button
|
|
if (!(btn->uiFlags & BUTTON_ENABLED))
|
|
return;
|
|
|
|
if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
|
|
{
|
|
btn->uiFlags|=(BUTTON_CLICKED_ON);
|
|
}
|
|
else if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
if( btn->uiFlags & BUTTON_CLICKED_ON )
|
|
{
|
|
|
|
// reset button
|
|
btn->uiFlags&=~(BUTTON_CLICKED_ON);
|
|
// Madd
|
|
/* if( LaptopSaveInfo.fIMPCompletedFlag )
|
|
{
|
|
// already here, leave
|
|
return;
|
|
}
|
|
*/
|
|
if( LaptopSaveInfo.iCurrentBalance < COST_OF_PROFILE )
|
|
{
|
|
// not enough
|
|
return;
|
|
}
|
|
|
|
// line moved by CJC Nov 28 2002 to AFTER the check for money
|
|
LaptopSaveInfo.fIMPCompletedFlag = TRUE;
|
|
|
|
// charge the player
|
|
AddTransactionToPlayersBook(IMP_PROFILE, (UINT8)(PLAYER_GENERATED_CHARACTER_ID + LaptopSaveInfo.iVoiceId), GetWorldTotalMin( ), - ( COST_OF_PROFILE ) );
|
|
AddHistoryToPlayersLog( HISTORY_CHARACTER_GENERATED, 0,GetWorldTotalMin( ), -1, -1 );
|
|
AddCharacterToPlayersTeam( );
|
|
|
|
// write the created imp merc
|
|
WriteOutCurrentImpCharacter( ( UINT8 )( PLAYER_GENERATED_CHARACTER_ID + LaptopSaveInfo.iVoiceId ) );
|
|
|
|
fButtonPendingFlag = TRUE;
|
|
iCurrentImpPage = IMP_HOME_PAGE;
|
|
|
|
//Kaiden: Below is the Imp personality E-mail as it was.
|
|
/*
|
|
// send email notice
|
|
//AddEmail(IMP_EMAIL_PROFILE_RESULTS, IMP_EMAIL_PROFILE_RESULTS_LENGTH, IMP_PROFILE_RESULTS, GetWorldTotalMin( ) );
|
|
AddFutureDayStrategicEvent( EVENT_DAY2_ADD_EMAIL_FROM_IMP, 60 * 7, 0, 2 );
|
|
*/
|
|
|
|
//Kaiden: And here is my Answer to the IMP E-mails only
|
|
// profiling the last IMP made. You get the results immediately
|
|
AddEmail(IMP_EMAIL_PROFILE_RESULTS, IMP_EMAIL_PROFILE_RESULTS_LENGTH, IMP_PROFILE_RESULTS, GetWorldTotalMin( ), PLAYER_GENERATED_CHARACTER_ID + LaptopSaveInfo.iVoiceId );
|
|
|
|
//RenderCharProfile( );
|
|
|
|
ResetCharacterStats();
|
|
|
|
//Display a popup msg box telling the user when and where the merc will arrive
|
|
//DisplayPopUpBoxExplainingMercArrivalLocationAndTime( PLAYER_GENERATED_CHARACTER_ID + LaptopSaveInfo.iVoiceId );
|
|
|
|
//reset the id of the last merc so we dont get the DisplayPopUpBoxExplainingMercArrivalLocationAndTime() pop up box in another screen by accident
|
|
LaptopSaveInfo.sLastHiredMerc.iIdOfMerc = -1;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// fixed? by CJC Nov 28 2002
|
|
void BtnIMPConfirmNo( GUI_BUTTON *btn,INT32 reason )
|
|
{
|
|
// btn callback for IMP Homepage About US button
|
|
if (!(btn->uiFlags & BUTTON_ENABLED))
|
|
return;
|
|
|
|
if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
|
|
{
|
|
btn->uiFlags|=(BUTTON_CLICKED_ON);
|
|
}
|
|
else if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
if( btn->uiFlags & BUTTON_CLICKED_ON )
|
|
{
|
|
|
|
iCurrentImpPage = IMP_FINISH;
|
|
|
|
/*
|
|
|
|
LaptopSaveInfo.fIMPCompletedFlag = FALSE;
|
|
ResetCharacterStats();
|
|
|
|
fButtonPendingFlag = TRUE;
|
|
iCurrentImpPage = IMP_HOME_PAGE;
|
|
*/
|
|
/*
|
|
if( fNoAlreadySelected == TRUE )
|
|
{
|
|
// already selected no
|
|
fButtonPendingFlag = TRUE;
|
|
iCurrentImpPage = IMP_HOME_PAGE;
|
|
}
|
|
fNoAlreadySelected = TRUE;
|
|
*/
|
|
btn->uiFlags&=~(BUTTON_CLICKED_ON);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
void BtnIMPConfirmNo( GUI_BUTTON *btn,INT32 reason )
|
|
{
|
|
|
|
|
|
// btn callback for IMP Homepage About US button
|
|
if (!(btn->uiFlags & BUTTON_ENABLED))
|
|
return;
|
|
|
|
if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
|
|
{
|
|
btn->uiFlags|=(BUTTON_CLICKED_ON);
|
|
}
|
|
else if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
|
{
|
|
if( btn->uiFlags & BUTTON_CLICKED_ON )
|
|
{
|
|
LaptopSaveInfo.fIMPCompletedFlag = TRUE;
|
|
if( fNoAlreadySelected == TRUE )
|
|
{
|
|
// already selected no
|
|
fButtonPendingFlag = TRUE;
|
|
iCurrentImpPage = IMP_HOME_PAGE;
|
|
}
|
|
fNoAlreadySelected = TRUE;
|
|
btn->uiFlags&=~(BUTTON_CLICKED_ON);
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
#define PROFILE_HAS_SKILL_TRAIT( p, t ) ((p->bSkillTrait == t) || (p->bSkillTrait2 == t))
|
|
|
|
|
|
void GiveItemsToPC( UINT8 ubProfileId )
|
|
{
|
|
MERCPROFILESTRUCT *pProfile;
|
|
|
|
|
|
// gives starting items to merc
|
|
// NOTE: Any guns should probably be from those available in regular gun set
|
|
|
|
pProfile = &(gMercProfiles[ubProfileId]);
|
|
|
|
|
|
// STANDARD EQUIPMENT
|
|
|
|
GiveIMPItems(pProfile, 100, IMP_DEFAULT);
|
|
GiveIMPRandomItems(pProfile, IMP_RANDOMDEFAULT);
|
|
|
|
|
|
// kevlar vest, leggings, & helmet
|
|
// MakeProfileInvItemThisSlot(pProfile, VESTPOS, FLAK_JACKET, 100, 1);
|
|
|
|
GiveIMPItems (pProfile,pProfile->bWisdom,IMP_WISDOM);
|
|
|
|
|
|
//if ( PreRandom( 100 ) < (UINT32) pProfile->bWisdom )
|
|
//{
|
|
// MakeProfileInvItemThisSlot(pProfile, HELMETPOS, STEEL_HELMET, 100, 1);
|
|
//}
|
|
|
|
// canteen
|
|
// MakeProfileInvItemThisSlot(pProfile, SMALLPOCK4POS, CANTEEN, 100, 1);
|
|
|
|
GiveIMPItems (pProfile,pProfile->bMarksmanship,IMP_MARKSMANSHIP);
|
|
|
|
|
|
//Give ANY imp the calico
|
|
// MakeProfileInvItemThisSlot( pProfile, HANDPOS, M950, 100, 1);
|
|
|
|
|
|
|
|
//No ammo clip MakeProfileInvItemThisSlot( pProfile, SMALLPOCK1POS, CLIP9_30, 100, 2);
|
|
|
|
/*
|
|
Ja25 IMP only gets 1 gun now
|
|
|
|
|
|
|
|
|
|
if (pProfile->bMarksmanship >= 80)
|
|
{
|
|
// good shooters get a better & matching ammo
|
|
MakeProfileInvItemThisSlot( pProfile, HANDPOS, MP5K, 100, 1);
|
|
MakeProfileInvItemThisSlot( pProfile, SMALLPOCK1POS, CLIP9_30, 100, 2);
|
|
}
|
|
else
|
|
{
|
|
// Automatic pistol, with matching ammo
|
|
MakeProfileInvItemThisSlot( pProfile, HANDPOS, BERETTA_93R, 100, 1 );
|
|
MakeProfileInvItemThisSlot( pProfile, SMALLPOCK1POS, CLIP9_15, 100, 3 );
|
|
}
|
|
*/
|
|
|
|
// OPTIONAL EQUIPMENT: depends on skills & special skills
|
|
|
|
GiveIMPItems (pProfile,pProfile->bMedical,IMP_MEDICAL);
|
|
|
|
//if (pProfile->bMedical >= 60)
|
|
//{
|
|
// // strong medics get full medic kit
|
|
// MakeProfileInvItemAnySlot(pProfile, MEDICKIT, 100, 1);
|
|
//}
|
|
//else
|
|
//if (pProfile->bMedical >= 30)
|
|
//{
|
|
// // passable medics get first aid kit
|
|
// MakeProfileInvItemAnySlot(pProfile, FIRSTAIDKIT, 100, 1);
|
|
//}
|
|
|
|
GiveIMPItems (pProfile,pProfile->bMechanical,IMP_MECHANICAL);
|
|
|
|
//if (pProfile->bMechanical >= 50)
|
|
//{
|
|
// // mechanics get toolkit
|
|
// MakeProfileInvItemAnySlot(pProfile, TOOLKIT, 100, 1);
|
|
//}
|
|
|
|
GiveIMPItems (pProfile,pProfile->bExplosive,IMP_EXPLOSIVE);
|
|
|
|
//if (pProfile->bExplosive >= 50)
|
|
//{
|
|
// // loonies get TNT & Detonator
|
|
//MakeProfileInvItemAnySlot(pProfile, TNT, 100, 1);
|
|
//MakeProfileInvItemAnySlot(pProfile, DETONATOR, 100, 1);
|
|
//}
|
|
|
|
GiveIMPItems (pProfile,pProfile->bAgility,IMP_AGILITY);
|
|
GiveIMPItems (pProfile,pProfile->bDexterity,IMP_DEXTERITY);
|
|
GiveIMPItems (pProfile,pProfile->bStrength,IMP_STRENGTH);
|
|
GiveIMPItems (pProfile,pProfile->bLifeMax,IMP_HEALTH);
|
|
GiveIMPItems (pProfile,pProfile->bLeadership,IMP_LEADERSHIP);
|
|
|
|
// check for special skills
|
|
if (PROFILE_HAS_SKILL_TRAIT(pProfile, LOCKPICKING) && ( iMechanical ) )
|
|
{
|
|
//MakeProfileInvItemAnySlot(pProfile, LOCKSMITHKIT, 100, 1);
|
|
GiveIMPRandomItems(pProfile,IMP_LOCKPICKING);
|
|
}
|
|
|
|
if (PROFILE_HAS_SKILL_TRAIT(pProfile, HANDTOHAND))
|
|
{
|
|
//MakeProfileInvItemAnySlot(pProfile, BRASS_KNUCKLES, 100, 1);
|
|
GiveIMPRandomItems(pProfile,IMP_HTH);
|
|
}
|
|
|
|
if (PROFILE_HAS_SKILL_TRAIT(pProfile, ELECTRONICS) && ( iMechanical ) )
|
|
{
|
|
//MakeProfileInvItemAnySlot(pProfile, METALDETECTOR, 100, 1);
|
|
GiveIMPRandomItems(pProfile,IMP_ELECTRONICS);
|
|
}
|
|
|
|
if (PROFILE_HAS_SKILL_TRAIT(pProfile, NIGHTOPS))
|
|
{
|
|
// MakeProfileInvItemAnySlot(pProfile, SILENCER, 100, 2);
|
|
GiveIMPRandomItems(pProfile,IMP_NIGHTOPS);
|
|
}
|
|
|
|
if (PROFILE_HAS_SKILL_TRAIT(pProfile, THROWING))
|
|
{
|
|
// MakeProfileInvItemAnySlot(pProfile, THROWING_KNIFE, 100, 1);
|
|
GiveIMPRandomItems(pProfile,IMP_THROWING);
|
|
}
|
|
|
|
if (PROFILE_HAS_SKILL_TRAIT(pProfile, STEALTHY))
|
|
{
|
|
// MakeProfileInvItemAnySlot(pProfile, SILENCER, 100, 1);
|
|
GiveIMPRandomItems(pProfile,IMP_STEALTHY);
|
|
}
|
|
|
|
if (PROFILE_HAS_SKILL_TRAIT(pProfile, KNIFING))
|
|
{
|
|
// MakeProfileInvItemAnySlot(pProfile, COMBAT_KNIFE, 100, 1);
|
|
GiveIMPRandomItems(pProfile,IMP_KNIFING);
|
|
}
|
|
|
|
if (PROFILE_HAS_SKILL_TRAIT(pProfile, CAMOUFLAGED)) // TODO: Madd - other camouflage types, once we figure out a way to enable more traits
|
|
{
|
|
// MakeProfileInvItemAnySlot(pProfile, CAMOUFLAGEKIT, 100, 1);
|
|
GiveIMPRandomItems(pProfile,IMP_CAMOUFLAGED);
|
|
}
|
|
|
|
if (PROFILE_HAS_SKILL_TRAIT(pProfile, AMBIDEXT))
|
|
{
|
|
// MakeProfileInvItemAnySlot(pProfile, M950, 100, 1);
|
|
GiveIMPRandomItems(pProfile,IMP_AMBIDEXTROUS);
|
|
}
|
|
|
|
if (PROFILE_HAS_SKILL_TRAIT(pProfile, MARTIALARTS))
|
|
{
|
|
GiveIMPRandomItems(pProfile,IMP_MARTIALARTS);
|
|
}
|
|
|
|
if (PROFILE_HAS_SKILL_TRAIT(pProfile, ONROOF))
|
|
{
|
|
GiveIMPRandomItems(pProfile,IMP_ROOFTOPS);
|
|
}
|
|
|
|
if (PROFILE_HAS_SKILL_TRAIT(pProfile, TEACHING))
|
|
{
|
|
GiveIMPRandomItems(pProfile,IMP_TEACHING);
|
|
}
|
|
|
|
if (PROFILE_HAS_SKILL_TRAIT(pProfile, AUTO_WEAPS))
|
|
{
|
|
GiveIMPRandomItems(pProfile,IMP_AUTOWEAPONS);
|
|
}
|
|
|
|
if (PROFILE_HAS_SKILL_TRAIT(pProfile, HEAVY_WEAPS ))
|
|
{
|
|
GiveIMPRandomItems(pProfile,IMP_HEAVYWEAPONS);
|
|
}
|
|
|
|
if (PROFILE_HAS_SKILL_TRAIT(pProfile, THIEF ))
|
|
{
|
|
GiveIMPRandomItems(pProfile,IMP_THIEF);
|
|
}
|
|
}
|
|
|
|
|
|
void MakeProfileInvItemAnySlot(MERCPROFILESTRUCT *pProfile, UINT16 usItem, UINT8 ubStatus, UINT8 ubHowMany)
|
|
{
|
|
INT32 iSlot;
|
|
|
|
iSlot = FirstFreeBigEnoughPocket(pProfile, usItem);
|
|
|
|
if (iSlot == -1)
|
|
{
|
|
// no room, item not received
|
|
return;
|
|
}
|
|
|
|
// put the item into that slot
|
|
MakeProfileInvItemThisSlot(pProfile, iSlot, usItem, ubStatus, ubHowMany);
|
|
}
|
|
|
|
|
|
void MakeProfileInvItemThisSlot(MERCPROFILESTRUCT *pProfile, UINT32 uiPos, UINT16 usItem, UINT8 ubStatus, UINT8 ubHowMany)
|
|
{
|
|
pProfile->inv[uiPos] = usItem;
|
|
pProfile->bInvStatus[uiPos] = ubStatus;
|
|
pProfile->bInvNumber[uiPos] = ubHowMany;
|
|
}
|
|
|
|
|
|
INT32 FirstFreeBigEnoughPocket(MERCPROFILESTRUCT *pProfile, UINT16 usItem)
|
|
{
|
|
UINT32 uiPos;
|
|
|
|
|
|
// if it fits into a small pocket
|
|
if (Item[usItem].ubPerPocket != 0)
|
|
{
|
|
// check small pockets first
|
|
for (uiPos = SMALLPOCK1POS; uiPos <= SMALLPOCK8POS; uiPos++)
|
|
{
|
|
if (pProfile->inv[uiPos] == NONE)
|
|
{
|
|
return(uiPos);
|
|
}
|
|
}
|
|
}
|
|
|
|
// check large pockets
|
|
for (uiPos = BIGPOCK1POS; uiPos <= BIGPOCK4POS; uiPos++)
|
|
{
|
|
if (pProfile->inv[uiPos] == NONE)
|
|
{
|
|
return(uiPos);
|
|
}
|
|
}
|
|
|
|
|
|
return(-1);
|
|
}
|
|
|
|
|
|
void WriteOutCurrentImpCharacter( INT32 iProfileId )
|
|
{
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("WriteOutCurrentImpCharacter: IMP.dat"));
|
|
char zImpFileName[13];
|
|
strcpy(zImpFileName,IMP_MERC_FILENAME);
|
|
strcat(zImpFileName,IMP_FILENAME_SUFFIX);
|
|
WriteOutCurrentImpCharacter ( iProfileId, zImpFileName);
|
|
|
|
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("WriteOutCurrentImpCharacter: Nickname.dat"));
|
|
|
|
char zFileName[13];
|
|
char temp;
|
|
|
|
for(int i=0;i < 9;i++) // Madd: I couldn't get strcpy or anything to work here... weird... if s/o wants to fix it, go ahead
|
|
{
|
|
temp = (char) gMercProfiles[iProfileId].zNickname[i];
|
|
zFileName[i] = temp;
|
|
}
|
|
|
|
strcat(zFileName,IMP_FILENAME_SUFFIX);
|
|
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("WriteOutCurrentImpCharacter: %s", zFileName));
|
|
WriteOutCurrentImpCharacter ( iProfileId, zFileName);
|
|
}
|
|
|
|
void WriteOutCurrentImpCharacter( INT32 iProfileId, STR fileName )
|
|
{
|
|
// grab the profile number and write out what is contained there in
|
|
HWFILE hFile;
|
|
UINT32 uiBytesWritten = 0;
|
|
|
|
// open the file for writing
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("WriteOutCurrentImpCharacter: %s", fileName));
|
|
hFile = FileOpen(fileName, FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE);
|
|
|
|
// write out the profile id
|
|
if (!FileWrite(hFile, &iProfileId, sizeof( INT32 ), &uiBytesWritten))
|
|
{
|
|
if (hFile)
|
|
FileClose(hFile);
|
|
return;
|
|
}
|
|
|
|
// write out the portrait id
|
|
if (!FileWrite(hFile, &iPortraitNumber, sizeof( INT32 ), &uiBytesWritten))
|
|
{
|
|
if (hFile)
|
|
FileClose(hFile);
|
|
return;
|
|
}
|
|
|
|
// write out the profile itself
|
|
if (!FileWrite(hFile, &gMercProfiles[ iProfileId ], sizeof( MERCPROFILESTRUCT ), &uiBytesWritten))
|
|
{
|
|
if (hFile)
|
|
FileClose(hFile);
|
|
return;
|
|
}
|
|
|
|
// close file
|
|
if (hFile)
|
|
FileClose(hFile);
|
|
|
|
return;
|
|
}
|
|
|
|
BOOLEAN ImpExists ( STR nickName )
|
|
{
|
|
char zFileName[13];
|
|
|
|
strcpy(zFileName,nickName);
|
|
strcat(zFileName,IMP_FILENAME_SUFFIX);
|
|
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("ImpExists: %s", (STR) zFileName));
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("ImpExists: %d", FileExistsNoDB(zFileName) ));
|
|
|
|
return FileExistsNoDB(zFileName);
|
|
}
|
|
|
|
BOOLEAN LoadImpCharacter( STR nickName )
|
|
{
|
|
INT32 iProfileId = 0;
|
|
HWFILE hFile;
|
|
UINT32 uiBytesRead = 0;
|
|
|
|
char zFileName[13];
|
|
|
|
strcpy(zFileName,nickName);
|
|
strcat(zFileName,IMP_FILENAME_SUFFIX);
|
|
|
|
// open the file for writing
|
|
hFile = FileOpen(zFileName, FILE_ACCESS_READ, FALSE);
|
|
|
|
// valid file?
|
|
if( hFile == -1 )
|
|
{
|
|
DoLapTopMessageBox( MSG_BOX_IMP_STYLE, pImpPopUpStrings[ 7 ], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, NULL);
|
|
return FALSE;
|
|
}
|
|
|
|
// read in the profile
|
|
|
|
if (!FileRead(hFile, &iProfileId,sizeof( INT32 ), &uiBytesRead))
|
|
{
|
|
DoLapTopMessageBox( MSG_BOX_IMP_STYLE, pImpPopUpStrings[ 7 ], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, NULL);
|
|
return FALSE;
|
|
}
|
|
|
|
// read in the portrait
|
|
if (!FileRead(hFile, &iPortraitNumber ,sizeof( INT32 ), &uiBytesRead))
|
|
{
|
|
DoLapTopMessageBox( MSG_BOX_IMP_STYLE, pImpPopUpStrings[ 7 ], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, NULL);
|
|
return FALSE;
|
|
}
|
|
|
|
// Set the ID of the new IMP
|
|
iProfileId = GetFreeIMPSlot(iProfileId);
|
|
|
|
// We can create the new imp, beacuse we found an empty slot
|
|
if (iProfileId != -1)
|
|
{
|
|
LaptopSaveInfo.iVoiceId = iProfileId - PLAYER_GENERATED_CHARACTER_ID;
|
|
|
|
// read in the profile
|
|
if (!FileRead(hFile, &gMercProfiles[ iProfileId ] ,sizeof( MERCPROFILESTRUCT ), &uiBytesRead))
|
|
{
|
|
DoLapTopMessageBox( MSG_BOX_IMP_STYLE, pImpPopUpStrings[ 7 ], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, NULL);
|
|
return FALSE;
|
|
}
|
|
|
|
// close file
|
|
FileClose(hFile);
|
|
|
|
if( LaptopSaveInfo.iCurrentBalance < COST_OF_PROFILE )
|
|
{
|
|
DoLapTopMessageBox( MSG_BOX_IMP_STYLE, pImpPopUpStrings[ 3 ], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, NULL);
|
|
|
|
// not enough
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// charge the player
|
|
// is the character male?
|
|
fCharacterIsMale = ( gMercProfiles[ iProfileId ].bSex == MALE );
|
|
fLoadingCharacterForPreviousImpProfile = TRUE;
|
|
AddTransactionToPlayersBook(IMP_PROFILE,0, GetWorldTotalMin( ), - ( COST_OF_PROFILE ) );
|
|
AddHistoryToPlayersLog( HISTORY_CHARACTER_GENERATED, 0,GetWorldTotalMin( ), -1, -1 );
|
|
LaptopSaveInfo.iVoiceId = iProfileId - PLAYER_GENERATED_CHARACTER_ID;
|
|
AddCharacterToPlayersTeam( );
|
|
AddFutureDayStrategicEvent( EVENT_DAY2_ADD_EMAIL_FROM_IMP, 60 * 7, 0, 2 );
|
|
LaptopSaveInfo.fIMPCompletedFlag = TRUE;
|
|
fPausedReDrawScreenFlag = TRUE;
|
|
fLoadingCharacterForPreviousImpProfile = FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
// You cannot have more than 3 I.M.P characters with the same gender on your team.
|
|
DoLapTopMessageBox( MSG_BOX_IMP_STYLE, pImpPopUpStrings[ 9 ], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, NULL);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void ResetIMPCharactersEyesAndMouthOffsets( UINT8 ubMercProfileID )
|
|
{
|
|
// ATE: Check boundary conditions!
|
|
if( ( ( gMercProfiles[ ubMercProfileID ].ubFaceIndex - 200 ) > 16 ) || ( ubMercProfileID >= PROF_HUMMER ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
gMercProfiles[ ubMercProfileID ].usEyesX = uiEyeXPositions[ gMercProfiles[ ubMercProfileID ].ubFaceIndex - 200 ];
|
|
gMercProfiles[ ubMercProfileID ].usEyesY = uiEyeYPositions[ gMercProfiles[ ubMercProfileID ].ubFaceIndex - 200 ];
|
|
|
|
|
|
gMercProfiles[ ubMercProfileID ].usMouthX = uiMouthXPositions[ gMercProfiles[ ubMercProfileID ].ubFaceIndex - 200 ];
|
|
gMercProfiles[ ubMercProfileID ].usMouthY = uiMouthYPositions[ gMercProfiles[ ubMercProfileID ].ubFaceIndex - 200 ];
|
|
}
|
|
|
|
|
|
void GiveIMPRandomItems( MERCPROFILESTRUCT *pProfile, UINT8 typeIndex )
|
|
{
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("GiveIMPRandomItems: typeIndex = %d",typeIndex ));
|
|
|
|
UINT16 usItem = 0;
|
|
INT32 iChoice;
|
|
|
|
if ( gIMPItemChoices[ typeIndex ].ubChoices <= 0 )
|
|
return;
|
|
|
|
for ( int i=0; i < gIMPItemChoices[typeIndex].ubNumItems ;i++ )
|
|
{
|
|
while (usItem == 0 )
|
|
{
|
|
iChoice = Random(gIMPItemChoices[ typeIndex ].ubChoices);
|
|
usItem = gIMPItemChoices[ typeIndex ].bItemNo[ iChoice ];
|
|
if (!ItemIsLegal(usItem))
|
|
usItem=0;
|
|
}
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("GiveIMPRandomItems: typeIndex = %d, usItem = %d ",typeIndex, usItem ));
|
|
if ( usItem > 0 )
|
|
MakeProfileInvItemAnySlot(pProfile,usItem,100,1);
|
|
|
|
// give ammo for guns
|
|
if ( Item[usItem].usItemClass == IC_GUN && !Item[usItem].rocketlauncher )
|
|
{
|
|
usItem = DefaultMagazine(usItem);
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("GiveIMPRandomItems: give ammo typeIndex = %d, usItem = %d ",typeIndex, usItem ));
|
|
MakeProfileInvItemAnySlot(pProfile,usItem,100,(1+Random(3)));
|
|
}
|
|
|
|
// give launchables for launchers
|
|
if ( Item[usItem].usItemClass == IC_LAUNCHER )
|
|
{
|
|
usItem = PickARandomLaunchable(usItem);
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("GiveIMPRandomItems: give launchable typeIndex = %d, usItem = %d",typeIndex, usItem ));
|
|
MakeProfileInvItemAnySlot(pProfile,usItem,100,(1+Random(3)));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void GiveIMPItems( MERCPROFILESTRUCT *pProfile, INT8 abilityValue, UINT8 typeIndex )
|
|
{
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("GiveIMPItems: typeIndex = %d, abilityValue = %d",typeIndex,abilityValue ));
|
|
|
|
UINT16 usItem = 0;
|
|
INT32 iChoice;
|
|
|
|
if ( gIMPItemChoices[ typeIndex ].ubChoices <= 0 )
|
|
return;
|
|
|
|
iChoice = (UINT32) (abilityValue / (100 / gIMPItemChoices[ typeIndex ].ubChoices)) ;
|
|
|
|
if ( iChoice >= gIMPItemChoices[ typeIndex ].ubChoices )
|
|
iChoice = gIMPItemChoices[ typeIndex ].ubChoices - 1;
|
|
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("GiveIMPItems: 1 iChoice = %d",iChoice));
|
|
for ( int i=0; i < gIMPItemChoices[typeIndex].ubNumItems ;i++ )
|
|
{
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("GiveIMPItems: 2 iChoice = %d",iChoice));
|
|
usItem = gIMPItemChoices[ typeIndex ].bItemNo[ iChoice ];
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("GiveIMPItems: typeIndex = %d, usItem = %d, iChoice = %d, abilityValue = %d",typeIndex, usItem,iChoice, abilityValue ));
|
|
if ( usItem > 0 && ItemIsLegal(usItem))
|
|
{
|
|
MakeProfileInvItemAnySlot(pProfile,usItem,100,1);
|
|
|
|
|
|
// give ammo for guns
|
|
if ( Item[usItem].usItemClass == IC_GUN && !Item[usItem].rocketlauncher )
|
|
{
|
|
usItem = DefaultMagazine(usItem);
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("GiveIMPItems: give ammo typeIndex = %d, usItem = %d",typeIndex, usItem ));
|
|
MakeProfileInvItemAnySlot(pProfile,usItem,100,(1+Random(3)));
|
|
}
|
|
|
|
// give launchables for launchers
|
|
if ( Item[usItem].usItemClass == IC_LAUNCHER )
|
|
{
|
|
usItem = PickARandomLaunchable(usItem);
|
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("GiveIMPItems: give launchable typeIndex = %d, usItem = %d",typeIndex, usItem ));
|
|
MakeProfileInvItemAnySlot(pProfile,usItem,100,(1+Random(3)));
|
|
}
|
|
}
|
|
iChoice--;
|
|
if (iChoice < 0)
|
|
iChoice = 0;
|
|
}
|
|
|
|
|
|
}
|
|
|