Merged from revision: 6981

Enabled auto-taking for concertina/sandbags (by Sevenfm)
- items are taken from current merc's inventory
- works only in realtime
- when filling sandbags, filled sandbag is dropped, and new empty is taken from inventory
- you need to press [shift] while clicking with hammer for this feature to be activated

Autofire bullets (by Sevenfm)
Set default number of autofire bullets:
0 = Max bullets allowed with max aiming
1..10 = Set default number of bullets

1. For MPs and SMGs
SET_DEFAULT_AUTOFIRE_BULLETS_SMG = 1
2. For ARs, Rifles and Shotguns
SET_DEFAULT_AUTOFIRE_BULLETS_AR = 1
3. For MGs
SET_DEFAULT_AUTOFIRE_BULLETS_MG = 1

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6982 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2014-02-26 18:56:22 +00:00
parent 8923608027
commit cfed0ed8a1
8 changed files with 153 additions and 28 deletions
+5
View File
@@ -1025,6 +1025,11 @@ void LoadGameExternalOptions()
// HEADROCK HAM B2.6/2/1: Toggle new Burst/Auto Targeting Cursors: 0=neither, 1=both, 2=Burst, 3=Auto
gGameExternalOptions.ubNewCTHBars = iniReader.ReadInteger("Tactical Interface Settings","USE_NEW_BURST-AUTO_TARGETING_CURSORS", 0, 0, 3);
// sevenfm: default autofire bullets
gGameExternalOptions.ubSetDefaultAutofireBulletsSMG = iniReader.ReadInteger("Tactical Interface Settings","SET_DEFAULT_AUTOFIRE_BULLETS_SMG", 1, 0, 10);
gGameExternalOptions.ubSetDefaultAutofireBulletsAR = iniReader.ReadInteger("Tactical Interface Settings","SET_DEFAULT_AUTOFIRE_BULLETS_AR", 1, 0, 10);
gGameExternalOptions.ubSetDefaultAutofireBulletsMG = iniReader.ReadInteger("Tactical Interface Settings","SET_DEFAULT_AUTOFIRE_BULLETS_MG", 1, 0, 10);
// HEADROCK HAM B2.7: When turned on, this will give a CTH approximation instead of an exact value, on CTH Bars and "F" key feedback.
gGameExternalOptions.fApproximateCTH = iniReader.ReadBoolean("Tactical Interface Settings","INACCURATE_CTH_READOUT", FALSE);
+5
View File
@@ -932,6 +932,11 @@ typedef struct
// HEADROCK HAM B2.6/2/1: Toggle new Burst/Auto CTH bars: 0=neither, 1=both, 2=Burst, 3=Auto
UINT8 ubNewCTHBars;
// sevenfm: default autofire bullets
UINT8 ubSetDefaultAutofireBulletsSMG;
UINT8 ubSetDefaultAutofireBulletsAR;
UINT8 ubSetDefaultAutofireBulletsMG;
// CHRISL: Changed from a simple flag to two externalized values for more modder control over AI suppression
UINT16 ubAISuppressionMinimumMagSize;
UINT16 ubAISuppressionMinimumAmmo;
+12 -12
View File
@@ -115,7 +115,7 @@ void RemoveBlueFlagDialogueCallBack( UINT8 ubExitValue );
INT32 CheckBombDisarmChance(void);
void ExtendedDisarmMessageBox(void);
void ExtendedBoobyTrapMessageBoxCallBack( UINT8 ubExitValue );
void HandleTakeNewBombFromIventory(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj);
void HandleTakeNewBombFromInventory(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj);
void MineSpottedMessageBoxCallBack( UINT8 ubExitValue );
void CheckForPickedOwnership( void );
void BoobyTrapInMapScreenMessageBoxCallBack( UINT8 ubExitValue );
@@ -235,6 +235,12 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
// "attached weapon"
pSoldier->usAttackingWeapon = usHandItem;
// sevenfm: set shift flag for auto-taking of next item from inventory
if( fFromUI && _KeyDown(SHIFT) )
gfShiftBombPlant = TRUE;
else
gfShiftBombPlant = FALSE;
// Find soldier flags depend on if it's our own merc firing or a NPC
//if ( FindSoldier( sGridNo, &usSoldierIndex, &uiMercFlags, FIND_SOLDIER_GRIDNO ) )
if ( ( usSoldierIndex = WhoIsThere2( sGridNo, bLevel ) ) != NOBODY )
@@ -1517,13 +1523,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
if ( fDropBomb )
{
// Save gridno....
pSoldier->aiData.sPendingActionData2 = sGridNo;
// sevenfm: set shift flag for auto-taking of next mine from inventory (Improved Bomb Planting)
if( fFromUI && _KeyDown(SHIFT) )
gfShiftBombPlant = TRUE;
else
gfShiftBombPlant = FALSE;
pSoldier->aiData.sPendingActionData2 = sGridNo;
if ( pSoldier->sGridNo != sGridNo )
{
@@ -1842,7 +1842,7 @@ void HandleSoldierDropBomb( SOLDIERTYPE *pSoldier, INT32 sGridNo )
{
AddItemToPool( sGridNo, &gTempObject, BURIED, pSoldier->pathing.bLevel, WORLD_ITEM_ARMED_BOMB, 0 );
// sevenfm: take another item with same id from inventory, only REALTIME
HandleTakeNewBombFromIventory(pSoldier, &gTempObject);
HandleTakeNewBombFromInventory(pSoldier, &gTempObject);
// sevenfm: change cursor back to action if successfully taken new bomb
if ( gfShiftBombPlant && pSoldier->inv[ pSoldier->ubAttackingHand ].exists() )
guiPendingOverrideEvent = M_CHANGE_TO_ACTION;
@@ -5123,7 +5123,7 @@ void BombMessageBoxCallBack( UINT8 ubExitValue )
AddItemToPool( gsTempGridNo, &gTempObject, BURIED, gpTempSoldier->pathing.bLevel, WORLD_ITEM_ARMED_BOMB, 0 );
// sevenfm: set flag only if planting tripwire
gpWorldLevelData[ gsTempGridNo ].uiFlags |= MAPELEMENT_PLAYER_MINE_PRESENT;
HandleTakeNewBombFromIventory(gpTempSoldier, &gTempObject);
HandleTakeNewBombFromInventory(gpTempSoldier, &gTempObject);
// sevenfm: change cursor back to action if successfully taken new bomb (also change mode back to action if using tripwire roll)
if ( gfShiftBombPlant && gpTempSoldier->inv[ gpTempSoldier->ubAttackingHand ].exists() )
guiPendingOverrideEvent = M_CHANGE_TO_ACTION;
@@ -7000,11 +7000,11 @@ void ExtendedBoobyTrapMessageBoxCallBack( UINT8 ubExitValue )
}
}
void HandleTakeNewBombFromIventory(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj)
void HandleTakeNewBombFromInventory(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj)
{
if( !( (gTacticalStatus.uiFlags & TURNBASED ) && (gTacticalStatus.uiFlags & INCOMBAT) ) &&
!pSoldier->inv[HANDPOS].exists() && gfShiftBombPlant )
{
pSoldier->TakeNewBombFromIventory(pObj->usItem);
pSoldier->TakeNewBombFromInventory(pObj->usItem);
}
}
+4
View File
@@ -103,6 +103,7 @@
//////////////////////////////////////////////////////////////////////
//extern BOOLEAN gfDisplayFullCountRingBurst;
extern BOOLEAN gfAutofireInitBulletNum;
extern UINT16 PickSoldierReadyAnimation( SOLDIERTYPE *pSoldier, BOOLEAN fEndReady, BOOLEAN fHipStance );
//#define AP_TO_AIM_TILE_IF_GETTING_READY 1
@@ -1846,6 +1847,9 @@ UINT32 UIHandleMChangeToAction( UI_EVENT *pUIEvent )
//guiNewUICursor = CONFIRM_MOVE_UICURSOR;
// sevenfm: this flag means that we'll need to initialize number of bullets for autofire
gfAutofireInitBulletNum = FALSE;
return( GAME_SCREEN );
}
+54 -7
View File
@@ -130,6 +130,9 @@ UINT16 usForceAnimState = INVALID_ANIMATION;//dnl ch70 170913
extern INT16 DirIncrementer[8];
// sevenfm: used in auto taking concertina/sandbag items from inventory
extern BOOLEAN gfShiftBombPlant;
#define PALETTEFILENAME "BINARYDATA\\ja2pal.dat"
#define LOW_MORALE_BATTLE_SND_THREASHOLD 35
@@ -16108,8 +16111,14 @@ BOOLEAN SOLDIERTYPE::UpdateMultiTurnAction()
// Build the thing
if ( BuildFortification( this->sMTActionGridNo, Item[ pObj->usItem ].usItemFlag ) )
{
UINT16 usItem = pObj->usItem;
// Erase 'material' item from our hand - we 'use' it to build the structure
DeleteObj( &(this->inv[HANDPOS]) );
// sevenfm: auto-taking of items
if( !(gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT) && gfShiftBombPlant )
{
TakeNewItemFromInventory( usItem );
}
// we gain a bit of experience...
StatChange( this, STRAMT, 4, TRUE );
@@ -16141,13 +16150,23 @@ BOOLEAN SOLDIERTYPE::UpdateMultiTurnAction()
{
// eventually search for the number of a sandbag item
if ( HasItemFlag(fullsandbagnr, FULL_SANDBAG) || GetFirstItemWithFlag(&fullsandbagnr, FULL_SANDBAG) )
{
// Erase 'material' item from our hand - we 'used' it to build the structure
{
INT8 bObjSlot = HANDPOS;
UINT16 usItem = pObj->usItem;
CreateItem( fullsandbagnr, 100, &gTempObject );
if( !(gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT) && gfShiftBombPlant )
{ // sevenfm: drop filled sandbag to the ground and take new empty from inventory
AddItemToPool( this->sGridNo, &gTempObject, 1, 0, 0, -1 );
DeleteObj( &(this->inv[HANDPOS]) );
TakeNewItemFromInventory( usItem );
}
else
{
SwapObjs( this, bObjSlot, &gTempObject, TRUE );
}
// sevenfm: added this to correctly update interface
DirtyMercPanelInterface( this, DIRTYLEVEL2 );
// we gain a bit of experience...
StatChange( this, STRAMT, 1, TRUE );
@@ -16250,7 +16269,7 @@ void SOLDIERTYPE::DropSectorEquipment()
}
// sevenfm: take item from inventory to HANDPOS
void SOLDIERTYPE::TakeNewBombFromIventory(UINT16 item)
void SOLDIERTYPE::TakeNewItemFromInventory(UINT16 usItem)
{
INT8 i;
OBJECTTYPE* pObj = NULL;
@@ -16258,6 +16277,10 @@ void SOLDIERTYPE::TakeNewBombFromIventory(UINT16 item)
if ( !UsingNewInventorySystem() )
return;
// this feature works now only in realtime
if( (gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT) )
return;
if(this->inv[HANDPOS].exists())
return;
@@ -16265,12 +16288,36 @@ void SOLDIERTYPE::TakeNewBombFromIventory(UINT16 item)
// search for item with same id
for ( i = 0; i < invsize; i++)
{
if ( ( this->inv[i].exists() == true ) && ( this->inv[i].usItem == item ) )
if ( ( this->inv[i].exists() == true ) && ( this->inv[i].usItem == usItem ) )
{
this->inv[i].MoveThisObjectTo(this->inv[HANDPOS], 1, this);
return;
}
}
}
// sevenfm: take item from inventory to HANDPOS
void SOLDIERTYPE::TakeNewBombFromInventory(UINT16 usItem)
{
INT8 i;
OBJECTTYPE* pObj = NULL;
INT8 invsize = (INT8)this->inv.size();
if ( !UsingNewInventorySystem() )
return;
if(this->inv[HANDPOS].exists())
return;
// search for item with same id
for ( i = 0; i < invsize; i++)
{
if ( ( this->inv[i].exists() == true ) && ( this->inv[i].usItem == usItem ) )
{
this->inv[i].MoveThisObjectTo(this->inv[HANDPOS], 1, this);
return;
}
}
// search for any item with class IC_BOMB
// take tripwire-activated item only if used item is tripwire activated
@@ -16280,8 +16327,8 @@ void SOLDIERTYPE::TakeNewBombFromIventory(UINT16 item)
Item[ this->inv[i].usItem ].usItemClass == IC_BOMB &&
Item[ this->inv[i].usItem ].ubCursor == BOMBCURS &&
!Item[ this->inv[i].usItem ].tripwire &&
( ( Item[ this->inv[i].usItem ].tripwireactivation && Item[item].tripwireactivation ) ||
( !Item[ this->inv[i].usItem ].tripwireactivation && !Item[item].tripwireactivation ) ) )
( ( Item[ this->inv[i].usItem ].tripwireactivation && Item[usItem].tripwireactivation ) ||
( !Item[ this->inv[i].usItem ].tripwireactivation && !Item[usItem].tripwireactivation ) ) )
{
this->inv[i].MoveThisObjectTo(this->inv[HANDPOS], 1, this);
return;
+2 -1
View File
@@ -1751,7 +1751,8 @@ public:
void DropSectorEquipment();
// sevenfm: Take new bomb with id = usItem from iventory to HANDPOS
void TakeNewBombFromIventory(UINT16 usItem);
void TakeNewBombFromInventory(UINT16 usItem);
void TakeNewItemFromInventory(UINT16 usItem);
// Flugente: switch hand item for gunsling weapon, or pistol, or knife
void SwitchWeapons( BOOLEAN fKnife = FALSE, BOOLEAN fSideArm = FALSE );
+65 -8
View File
@@ -60,10 +60,12 @@ UINT8 HandleApplyItemCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCurs
extern BOOLEAN HandleCheckForBadChangeToGetThrough( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pTargetSoldier, INT32 sTargetGridNo , INT8 bLevel );
UINT8 DefaultAutofireBulletsByGunClass( SOLDIERTYPE* pSoldier ); // added by Sevenfm
BOOLEAN gfCannotGetThrough = FALSE;
extern UINT32 guiUITargetSoldierId;
BOOLEAN gfDisplayFullCountRing = FALSE;
BOOLEAN gfAutofireInitBulletNum = FALSE;
UINT8 gubAimRingRanges[] = {30, 55, 75, 90}; // These are the cutoff ranges for the aiming rings
extern INT8 gbNumBurstLocations; //number of burst points
@@ -164,7 +166,6 @@ UINT8 GetProperItemCursor( UINT8 ubSoldierID, UINT16 ubItemIndex, INT32 usMapPos
sTargetGridNo = usMapPos;
}
ubItemCursor = GetActionModeCursor( pSoldier );
switch( ubItemCursor )
@@ -393,12 +394,14 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
{
DetermineCursorBodyLocation( (UINT8)gusSelectedSoldier, TRUE, TRUE );
}
UINT8 ubMaxBullets = 1;
INT8 bMaxAim;
if ( gTacticalStatus.uiFlags & TURNBASED && ( gTacticalStatus.uiFlags & INCOMBAT ) )
{
if(pSoldier->bDoAutofire)
{
if(pSoldier->bDoAutofire == 1) //try to maximize the # of bullets because 1 may not be optimal
// sevenfm: change number of autofire bullets only once when switching cursor to action mode or changing firing mode
if( !gfAutofireInitBulletNum )
{
INT16 sCurAPCosts, sAPCosts;
UINT16 usShotsLeft = pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft;
@@ -406,16 +409,27 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
{
usShotsLeft = min( (pSoldier->inv[ SECONDHANDPOS ][0]->data.gun.ubGunShotsLeft), usShotsLeft );
}
bMaxAim = pSoldier->aiData.bShownAimTime;
sCurAPCosts = CalcTotalAPsToAttack( pSoldier, usMapPos, TRUE, pSoldier->aiData.bShownAimTime);
// sevenfm: change default number of bullets in autofire according to ini settings
ubMaxBullets = DefaultAutofireBulletsByGunClass( pSoldier );
if( ubMaxBullets == 0 )
{
ubMaxBullets = usShotsLeft;
bMaxAim = maxAimLevels;
}
sCurAPCosts = CalcTotalAPsToAttack( pSoldier, usMapPos, TRUE, bMaxAim);
do
{
pSoldier->bDoAutofire++;
sAPCosts = CalcTotalAPsToAttack( pSoldier, usMapPos, TRUE, pSoldier->aiData.bShownAimTime);
}
while(EnoughPoints( pSoldier, sAPCosts, 0, FALSE ) && sAPCosts == sCurAPCosts && usShotsLeft >= pSoldier->bDoAutofire);
sAPCosts = CalcTotalAPsToAttack( pSoldier, usMapPos, TRUE, bMaxAim);
} // sevenfm: removed (sAPCosts <= sCurAPCosts) because EnoughPoints() is enough
while(EnoughPoints( pSoldier, sAPCosts, 0, FALSE ) && usShotsLeft >= pSoldier->bDoAutofire && pSoldier->bDoAutofire <= ubMaxBullets );
pSoldier->bDoAutofire--;
gfAutofireInitBulletNum = TRUE;
}
gfUIAutofireBulletCount = TRUE;
@@ -1283,9 +1297,15 @@ UINT8 HandleNonActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos , BO
if(gusUIFullTargetID == NOBODY && pSoldier->bDoAutofire && !pSoldier->flags.fDoSpread) //reset autofire if we move the mouse off the target, however don't reset it if we are spread-bursting
{
if(gTacticalStatus.uiFlags & TURNBASED && (gTacticalStatus.uiFlags & INCOMBAT ))
{
pSoldier->bDoAutofire = 1;
// sevenfm: init autofire bullet num next time when the cursor will be on target
gfAutofireInitBulletNum = FALSE;
}
else
{
pSoldier->bDoAutofire = 6;
}
pSoldier->flags.autofireLastStep = FALSE;
}
@@ -3605,7 +3625,6 @@ void HandleWheelAdjustCursor( SOLDIERTYPE *pSoldier, INT32 sMapPos, INT32 sDelta
}
}
//îáðàáîòêà êîëåñà áåç ïðèöåëüíîé î÷åðåäè if ïðèöåëüíàÿ î÷åðåäü îòêëþ÷åíà â .èíè
void HandleWheelAdjustCursorWOAB( SOLDIERTYPE *pSoldier, INT32 sMapPos, INT32 sDelta )
{
UINT16 usInHand;
@@ -3798,4 +3817,42 @@ void HandleWheelAdjustCursorWOAB( SOLDIERTYPE *pSoldier, INT32 sMapPos, INT32 sD
ErasePath( TRUE );
}
}
UINT8 DefaultAutofireBulletsByGunClass( SOLDIERTYPE* pSoldier )
{
UINT32 usItemClass;
UINT16 usItem;
UINT8 ubBullets = 1;
if( !pSoldier )
return 1;
if( !pSoldier->inv[ pSoldier->ubAttackingHand ].exists() )
return 1;
usItem = pSoldier->inv[ pSoldier->ubAttackingHand ].usItem;
usItemClass = Item[ usItem ].usItemClass;
if( usItemClass != IC_GUN )
return 1;
switch( Weapon[ Item[ usItem ].ubClassIndex ].ubWeaponType )
{
case GUN_M_PISTOL:
case GUN_PISTOL:
case GUN_SMG:
ubBullets = gGameExternalOptions.ubSetDefaultAutofireBulletsSMG;
break;
case GUN_AS_RIFLE:
case GUN_RIFLE:
case GUN_SN_RIFLE :
case GUN_SHOTGUN:
ubBullets = gGameExternalOptions.ubSetDefaultAutofireBulletsAR;
break;
case GUN_LMG:
ubBullets = gGameExternalOptions.ubSetDefaultAutofireBulletsMG;
break;
}
return ubBullets;
}
+6
View File
@@ -65,6 +65,9 @@ class SOLDIERTYPE;
extern INT8 gbCurrentRainIntensity;
//end rain
// sevenfm: this global variable is needed to correctly set default number of bullets for autofire
extern BOOLEAN gfAutofireInitBulletNum;
extern SECTOR_EXT_DATA SectorExternalData[256][4]; // added by Flugente
// HEADROCK HAM B1: Externalized both values to INI
@@ -11674,6 +11677,9 @@ void ChangeWeaponMode( SOLDIERTYPE * pSoldier )
if (pSoldier->bWeaponMode == WM_AUTOFIRE || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO || pSoldier->bWeaponMode == WM_ATTACHED_UB_AUTO)
{
// sevenfm: this flag means that we'll need to initialize number of bullets for autofire
gfAutofireInitBulletNum = FALSE;
pSoldier->bDoAutofire = 1;
pSoldier->bDoBurst = 1;
}