mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
Added missing #includes Added LUA scripting and console Changed the way tracers are visualized, so they work more like real tracers instead of a light fountain Fixed signedness of many grid variables used in GetMouseMapPos calls Fixed enemy weapon choosing: Sometimes a mortar is chosen but later rejected, but the grenade class was not reset. Caused assertion failure Added checks so enemies don't try to chuck RPG grenades with their hands Now possible to shoot a someone in the head if he's in water Fixed InitSightArrays to also clear soldier interrupt duel points. This was causing an assertion failure elsewhere in the code because the interrupt list still had soldiers on it sometimes when this function was called. Soldiers are much less willing to forfeit their turn over an attempt to use more APs than they have Removed early setting of muzzle flash. This would allow enemies to get an interrupt before you even fired. Fixed item dropping by AI. If AI tried to drop something while standing it would cause deadlock Change to greatly speed up closing the sector inventory window in an unloaded sector Added conditional compile flag to always give robot weapon ready advantage, even for 360 degree sighting Check builddefines.h for the conditional flags. Of greatest interest might be LUA_CONSOLE. This will cause the game to bring up a command console when run. However this console is severely lacking in many areas. If anybody knows of an open-source terminal/console that could be used instead, it would be appreciated. The existing console does bad things when you try to close it, and since it counts as a separate app, it pauses the game while it has focus. LUA scripting is very limited, basically just proof of concept. There is one global variable, the Soldiers array. An array index gives you the soldier in that slot in the currently loaded sector. The soldier has a few things that can be accessed: name (short name); fullname (long name); grid (current grid #, can be changed); walkto(grid) (function to walk to another grid); runto(grid) (function to run to another grid) git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@924 3b4a5df2-a311-0410-b5c6-a8a6f20db521
956 lines
26 KiB
C++
956 lines
26 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"
|
|
#include "weapons.h"
|
|
#include "Random.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, UINT8 ubHowMany);
|
|
|
|
// 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 )( LaptopSaveInfo.iIMPIndex ) ;
|
|
|
|
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)(LaptopSaveInfo.iIMPIndex), GetWorldTotalMin( ), - ( COST_OF_PROFILE ) );
|
|
AddHistoryToPlayersLog( HISTORY_CHARACTER_GENERATED, 0,GetWorldTotalMin( ), -1, -1 );
|
|
AddCharacterToPlayersTeam( );
|
|
|
|
// write the created imp merc
|
|
WriteOutCurrentImpCharacter( ( UINT8 )( LaptopSaveInfo.iIMPIndex ) );
|
|
|
|
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( ), LaptopSaveInfo.iIMPIndex );
|
|
|
|
//RenderCharProfile( );
|
|
|
|
ResetCharacterStats();
|
|
|
|
//Display a popup msg box telling the user when and where the merc will arrive
|
|
//DisplayPopUpBoxExplainingMercArrivalLocationAndTime( LaptopSaveInfo.iIMPIndex );
|
|
|
|
//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, ubHowMany);
|
|
|
|
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, UINT8 ubHowMany)
|
|
{
|
|
UINT32 uiPos;
|
|
|
|
if (ubHowMany == 1)
|
|
{
|
|
// check body spots
|
|
|
|
if ( pProfile->inv[HELMETPOS] == NONE && Item[usItem].usItemClass == IC_ARMOUR && Armour[Item[usItem].ubClassIndex].ubArmourClass == ARMOURCLASS_HELMET )
|
|
return HELMETPOS;
|
|
if ( pProfile->inv[VESTPOS] == NONE && Item[usItem].usItemClass == IC_ARMOUR && Armour[Item[usItem].ubClassIndex].ubArmourClass == ARMOURCLASS_VEST )
|
|
return VESTPOS;
|
|
if ( pProfile->inv[LEGPOS] == NONE && Item[usItem].usItemClass == IC_ARMOUR && Armour[Item[usItem].ubClassIndex].ubArmourClass == ARMOURCLASS_LEGGINGS )
|
|
return LEGPOS;
|
|
if ( pProfile->inv[HEAD1POS] == NONE && Item[usItem].usItemClass == IC_FACE && CompatibleFaceItem(usItem,pProfile->inv[HEAD2POS]) )
|
|
return HEAD1POS;
|
|
if ( pProfile->inv[HEAD2POS] == NONE && Item[usItem].usItemClass == IC_FACE && CompatibleFaceItem(usItem,pProfile->inv[HEAD1POS]) )
|
|
return HEAD2POS;
|
|
if ( pProfile->inv[HANDPOS] == NONE )
|
|
return HANDPOS;
|
|
if ( pProfile->inv[SECONDHANDPOS] == NONE )
|
|
return SECONDHANDPOS;
|
|
}
|
|
// 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", 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, iProfileId);
|
|
|
|
// We can create the new imp, beacuse we found an empty slot
|
|
if (iProfileId != -1)
|
|
{
|
|
LaptopSaveInfo.iIMPIndex = iProfileId;
|
|
|
|
// 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.iIMPIndex = iProfileId;
|
|
AddCharacterToPlayersTeam( );
|
|
// WANNE: Email is sent immediatly after the imp was created. So no need to send it later again
|
|
//AddFutureDayStrategicEvent( EVENT_DAY2_ADD_EMAIL_FROM_IMP, 60 * 7, 0, 2 );
|
|
LaptopSaveInfo.fIMPCompletedFlag = TRUE;
|
|
fPausedReDrawScreenFlag = TRUE;
|
|
fLoadingCharacterForPreviousImpProfile = FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
// close file
|
|
FileClose(hFile);
|
|
|
|
// WDS: Allow flexible numbers of IMPs of each sex
|
|
// note: check this
|
|
|
|
// 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(1)));
|
|
}
|
|
|
|
// 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,(2+Random(2)));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
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,(2+Random(2)));
|
|
}
|
|
|
|
// 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,(2+Random(2)));
|
|
}
|
|
}
|
|
iChoice--;
|
|
if (iChoice < 0)
|
|
iChoice = 0;
|
|
}
|
|
|
|
|
|
}
|
|
|