mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
New feature: guns can now be fed externally
- a machinegun can be fed by another emc if he has an ammo blet in his hands - a merc can also feed his gun with ammo belts in his inventory - the necessary tags can be set in Items.xml in the <ItemFlag> -tag - this feature can be turned on and off via the JA2_Options.iniReader - for more info, see http://www.bears-pit.com/board/ubbthreads.php/topics/307574/New_feature_Externally_fed_mac.html#Post307574 - this feature requires the newest GameDir files, as a new face icon was added git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5415 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+9
-7
@@ -1117,6 +1117,8 @@ void LoadGameExternalOptions()
|
||||
|
||||
gGameExternalOptions.fScopeModes = iniReader.ReadBoolean("Tactical Gameplay Settings","USE_SCOPE_MODES", FALSE);
|
||||
gGameExternalOptions.fDisplayScopeModes = iniReader.ReadBoolean("Tactical Gameplay Settings","DISPLAY_SCOPE_MODES", FALSE);
|
||||
|
||||
gGameExternalOptions.ubExternalFeeding = iniReader.ReadInteger("Tactical Gameplay Settings","EXTERNAL_FEEDING", 2, 0, 2);
|
||||
|
||||
// WANNE: Externalized grid number of new merc when they arrive with the helicopter (by Jazz)
|
||||
gGameExternalOptions.iInitialMercArrivalLocation = iniReader.ReadInteger("Tactical Gameplay Settings","INITIAL_MERC_ARRIVAL_LOCATION", 4870 );
|
||||
@@ -1396,15 +1398,15 @@ void LoadGameExternalOptions()
|
||||
//################# Tactical Food Settings ##################
|
||||
gGameExternalOptions.usFoodDigestionHourlyBaseFood = iniReader.ReadInteger("Tactical Food Settings", "FOOD_DIGESTION_HOURLY_BASE_FOOD", 20, 0, 250);
|
||||
gGameExternalOptions.usFoodDigestionHourlyBaseDrink = iniReader.ReadInteger("Tactical Food Settings", "FOOD_DIGESTION_HOURLY_BASE_DRINK", 130, 0, 250);
|
||||
gGameExternalOptions.sFoodDigestionSleep = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_SLEEP", 0.6, 0.0, 10.0);
|
||||
gGameExternalOptions.sFoodDigestionTravelVehicle = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_TRAVEL_VEHICLE", 0.8, 0.0, 10.0);
|
||||
gGameExternalOptions.sFoodDigestionTravel = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_TRAVEL", 1.5, 0.0, 10.0);
|
||||
gGameExternalOptions.sFoodDigestionAssignment = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_ASSIGNMENT", 0.9, 0.0, 10.0);
|
||||
gGameExternalOptions.sFoodDigestionOnDuty = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_ONDUTY", 1.0, 0.0, 10.0);
|
||||
gGameExternalOptions.sFoodDigestionCombat = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_COMBAT", 2.0, 0.0, 10.0);
|
||||
gGameExternalOptions.sFoodDigestionSleep = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_SLEEP", 0.6f, 0.0f, 10.0f);
|
||||
gGameExternalOptions.sFoodDigestionTravelVehicle = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_TRAVEL_VEHICLE", 0.8f, 0.0f, 10.0f);
|
||||
gGameExternalOptions.sFoodDigestionTravel = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_TRAVEL", 1.5f, 0.0f, 10.0f);
|
||||
gGameExternalOptions.sFoodDigestionAssignment = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_ASSIGNMENT", 0.9f, 0.0f, 10.0f);
|
||||
gGameExternalOptions.sFoodDigestionOnDuty = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_ONDUTY", 1.0f, 0.0f, 10.0f);
|
||||
gGameExternalOptions.sFoodDigestionCombat = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DIGESTION_COMBAT", 2.0f, 0.0f, 10.0f);
|
||||
|
||||
gGameExternalOptions.fFoodDecayInSectors = iniReader.ReadBoolean("Tactical Food Settings", "FOOD_DECAY_IN_SECTORS", TRUE);
|
||||
gGameExternalOptions.sFoodDecayModificator = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DECAY_MODIFICATOR", 1.0, 0.1, 10.0);
|
||||
gGameExternalOptions.sFoodDecayModificator = iniReader.ReadFloat("Tactical Food Settings", "FOOD_DECAY_MODIFICATOR", 1.0f, 0.1f, 10.0f);
|
||||
|
||||
//################# Strategic Gamestart Settings ##################
|
||||
|
||||
|
||||
@@ -1135,6 +1135,9 @@ typedef struct
|
||||
// Flugente: Scope Modes
|
||||
BOOLEAN fScopeModes; // allow the player to toggle between existing scopes/sights
|
||||
BOOLEAN fDisplayScopeModes; // allow display of scope modes
|
||||
|
||||
// Flugente: External Feeding
|
||||
UINT8 ubExternalFeeding; // allow external feeding of guns (0 = no, 1 = only for others, 2 = we can also fed ourselves)
|
||||
|
||||
BOOLEAN gBriefingRoom;
|
||||
BOOLEAN gEncyclopedia;
|
||||
|
||||
@@ -2302,6 +2302,21 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
|
||||
bNumRightIcons++;
|
||||
}
|
||||
}
|
||||
// Flugente: are we supplying ammo to someone else?
|
||||
if ( gGameExternalOptions.ubExternalFeeding > 0 )
|
||||
{
|
||||
UINT8 ubID1 = 0;
|
||||
UINT16 ubGunSlot1 = 0;
|
||||
UINT16 ubFaceSlot1 = 0;
|
||||
UINT8 ubID2 = 0;
|
||||
UINT16 ubGunSlot2 = 0;
|
||||
UINT16 ubFaceSlot2 = 0;
|
||||
if ( MercPtrs[ pFace->ubSoldierID ]->IsFeedingExternal( &ubID1, &ubGunSlot1, &ubFaceSlot1, &ubID2, &ubGunSlot2, &ubFaceSlot2 ) )
|
||||
{
|
||||
DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 21 );
|
||||
bNumRightIcons++;
|
||||
}
|
||||
}
|
||||
|
||||
switch( pSoldier->bAssignment )
|
||||
{
|
||||
|
||||
@@ -4128,6 +4128,38 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec
|
||||
mprintf( sNewX, sNewY, pStr );
|
||||
gprintfinvalidate( sNewX, sNewY, pStr );
|
||||
}
|
||||
|
||||
// Flugente: if ammo is used to feed a gun externally, show ammo count left on this ammo
|
||||
if ( gGameExternalOptions.ubExternalFeeding > 0 && (Item[pObject->usItem].usItemClass & (IC_AMMO)) && ObjectIsExternalFeeder(pSoldier, pObject) )
|
||||
{
|
||||
sNewY = sY + sHeight - 10;
|
||||
|
||||
UINT16 usAmmoItem = pObject->usItem;
|
||||
UINT16 usMagIndex = Item[usAmmoItem].ubClassIndex;
|
||||
UINT16 usAmmoMagSize = Magazine[usMagIndex].ubMagSize;
|
||||
UINT8 usAmmoAmmoType = Magazine[usMagIndex].ubAmmoType;
|
||||
|
||||
SetFontForeground ( AmmoTypes[usAmmoAmmoType].fontColour );
|
||||
|
||||
swprintf( pStr, L"%d", (*pObject)[iter]->data.ubShotsLeft );
|
||||
|
||||
// Get length of string
|
||||
uiStringLength=StringPixLength(pStr, ITEM_FONT );
|
||||
|
||||
sNewX = sX + 1;
|
||||
//sNewX = sX + sWidth - uiStringLength - 4;
|
||||
|
||||
if ( uiBuffer == guiSAVEBUFFER )
|
||||
{
|
||||
RestoreExternBackgroundRect( sNewX, sNewY, 20, 15 );
|
||||
}
|
||||
mprintf( sNewX, sNewY, pStr );
|
||||
gprintfinvalidate( sNewX, sNewY, pStr );
|
||||
|
||||
//sNewX = sX + 1;
|
||||
|
||||
//SetFontForeground( FONT_MCOLOR_DKGRAY );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -656,7 +656,7 @@ extern OBJECTTYPE gTempObject;
|
||||
#define AC_REMOTEDET 0x00100000 //1048576 // remote detonator for bombs
|
||||
#define AC_DEFUSE 0x00200000 //2097152 // defuse item for bombs
|
||||
#define AC_IRONSIGHT 0x00400000 //4194304 // for attachable Iron Sights
|
||||
#define AC_MISC12 0x00800000 //8388608
|
||||
#define AC_FEEDER 0x00800000 //8388608 // allow external feeding
|
||||
#define AC_MISC13 0x01000000 //16777216
|
||||
#define AC_MISC14 0x02000000 //33554432
|
||||
#define AC_MISC15 0x04000000 //67108864
|
||||
@@ -720,11 +720,11 @@ extern OBJECTTYPE gTempObject;
|
||||
#define WATER_DRUM 0x00000010 //16 // water drums allow to refill canteens in the sector they are in
|
||||
#define MEAT_BLOODCAT 0x00000020 //32 // retrieve this by gutting a bloodcat
|
||||
#define COW_MEAT 0x00000040 //64 // retrieve this by gutting a cow
|
||||
/*#define WH40K_DISPLACER 0x00000080 //128
|
||||
#define BELT_FED 0x00000080 //128 // item can be fed externally
|
||||
|
||||
#define WH40K_ROSARIUS 0x00000100 //256
|
||||
#define WH40K_SEAL 0x00000200 //512
|
||||
#define WH40K_POWER_WEAPON 0x00000400 //1024
|
||||
#define AMMO_BELT 0x00000100 //256 // this item can be used to feed externally
|
||||
#define AMMO_BELT_VEST 0x00000200 //512 // this is a vest that can contain AMMO_BELT items in its medium slots
|
||||
/*#define unused 0x00000400 //1024
|
||||
#define ENEMY_NET_4_LVL_3 0x00000800 //2048
|
||||
|
||||
#define ENEMY_NET_1_LVL_4 0x00001000 //4096
|
||||
|
||||
@@ -13981,3 +13981,128 @@ BOOLEAN GetFirstItemWithFlag( UINT16* pusItem, UINT32 aFlag )
|
||||
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// Flugente: check if object is currently fed from an external source (belts in inventory, other mercs)
|
||||
BOOLEAN ObjectIsBeingFedExternal(SOLDIERTYPE* pSoldier, OBJECTTYPE * pObject)
|
||||
{
|
||||
return( GetExternalFeedingObject(pSoldier, pObject) != NULL );
|
||||
}
|
||||
|
||||
// is this object currently used to feed an externally fed object? This can be in our or someone else's inventory
|
||||
BOOLEAN ObjectIsExternalFeeder(SOLDIERTYPE* pSoldier, OBJECTTYPE * pObject)
|
||||
{
|
||||
if ( !pSoldier || !pObject)
|
||||
return( FALSE );
|
||||
|
||||
UINT8 usSoldierFeedingTarget1 = 0;
|
||||
UINT16 usGunSlot1 = 0;
|
||||
UINT16 usAmmoSlot1 = 0;
|
||||
UINT8 usSoldierFeedingTarget2 = 0;
|
||||
UINT16 usGunSlot2 = 0;
|
||||
UINT16 usAmmoSlot2 = 0;
|
||||
if ( pSoldier->IsFeedingExternal(&usSoldierFeedingTarget1, &usGunSlot1, &usAmmoSlot1, &usSoldierFeedingTarget2, &usGunSlot2, &usAmmoSlot2) )
|
||||
{
|
||||
SOLDIERTYPE* pTargetSoldier = MercPtrs[usSoldierFeedingTarget1];
|
||||
|
||||
if ( pTargetSoldier && &(pSoldier->inv[usAmmoSlot1]) == pObject )
|
||||
return( TRUE );
|
||||
|
||||
pTargetSoldier = MercPtrs[usSoldierFeedingTarget2];
|
||||
|
||||
if ( pTargetSoldier && &(pSoldier->inv[usAmmoSlot2]) == pObject )
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
OBJECTTYPE* GetExternalFeedingObject(SOLDIERTYPE* pSoldier, OBJECTTYPE * pObject)
|
||||
{
|
||||
OBJECTTYPE* pObjExtMag = NULL;
|
||||
|
||||
if ( !pObject || !(pObject->exists()) || !pSoldier || !pSoldier->bActive || !pSoldier->bInSector || pSoldier->stats.bLife < OKLIFE )
|
||||
// how did we even get here?
|
||||
return false;
|
||||
|
||||
UINT16 usItem = pObject->usItem;
|
||||
|
||||
// if item is a gun that can be belt fed and still has shots left
|
||||
if ( Item[ usItem ].usItemClass == IC_GUN && ( HasItemFlag( usItem, BELT_FED ) || HasAttachmentOfClass(pObject, AC_FEEDER) ) && (*pObject)[0]->data.gun.ubGunShotsLeft > 0 )
|
||||
{
|
||||
// remember the caliber, magsize (TODO: really?) and type of ammo. They all have to fit
|
||||
UINT8 ubCalibre = Weapon[usItem].ubCalibre;
|
||||
UINT16 ubMagSize = Weapon[usItem].ubMagSize;
|
||||
UINT8 ubAmmoType = ubAmmoType = (*pObject)[0]->data.gun.ubGunAmmoType;
|
||||
|
||||
// now we now that this gun CAN be belt fed in the current situation. We now have to check if it IS
|
||||
// we will first check for other mercs who might feed us. Afterwards we look into our own inventory
|
||||
|
||||
// loop over other members of our team in this sector. This includes ourself, as our gun can be fed from a belt in our inventory
|
||||
SOLDIERTYPE* pTeamSoldier = NULL;
|
||||
INT32 cnt = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID;
|
||||
INT32 lastid = gTacticalStatus.Team[ pSoldier->bTeam ].bLastID;
|
||||
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt < lastid; ++cnt, ++pTeamSoldier)
|
||||
{
|
||||
// check if teamsoldier exists in this sector
|
||||
if ( !pTeamSoldier || !pTeamSoldier->bActive || !pTeamSoldier->bInSector || pTeamSoldier->stats.bLife < OKLIFE || pTeamSoldier->sSectorX != pSoldier->sSectorX || pTeamSoldier->sSectorY != pSoldier->sSectorY || pTeamSoldier->bSectorZ != pSoldier->bSectorZ )
|
||||
continue;
|
||||
|
||||
// check if both soldiers are on the same level
|
||||
if ( pSoldier->pathing.bLevel != pTeamSoldier->pathing.bLevel )
|
||||
continue;
|
||||
|
||||
// we check if that guy is feeding someone, and that someone is really us
|
||||
UINT8 usTeamSoldierFeedingTarget1 = 0;
|
||||
UINT16 usGunSlot1 = 0;
|
||||
UINT16 usAmmoSlot1 = 0;
|
||||
UINT8 usTeamSoldierFeedingTarget2 = 0;
|
||||
UINT16 usGunSlot2 = 0;
|
||||
UINT16 usAmmoSlot2 = 0;
|
||||
if ( pTeamSoldier->IsFeedingExternal(&usTeamSoldierFeedingTarget1, &usGunSlot1, &usAmmoSlot1, &usTeamSoldierFeedingTarget2, &usGunSlot2, &usAmmoSlot2) )
|
||||
{
|
||||
if ( usTeamSoldierFeedingTarget1 == pSoldier->ubID && pSoldier->inv[usGunSlot1] == (*pObject) )
|
||||
{
|
||||
if ( pTeamSoldier->inv[usAmmoSlot1].exists() && Item [ pTeamSoldier->inv[usAmmoSlot1].usItem ].usItemClass != IC_AMMO || pTeamSoldier->inv[usAmmoSlot1][0]->data.ubShotsLeft > 0 )
|
||||
{
|
||||
pObjExtMag = &(pTeamSoldier->inv[usAmmoSlot1]);
|
||||
return( pObjExtMag );
|
||||
}
|
||||
}
|
||||
|
||||
if ( usTeamSoldierFeedingTarget2 == pSoldier->ubID && pSoldier->inv[usGunSlot2] == (*pObject) )
|
||||
{
|
||||
if ( pTeamSoldier->inv[usAmmoSlot2].exists() && Item [ pTeamSoldier->inv[usAmmoSlot2].usItem ].usItemClass != IC_AMMO || pTeamSoldier->inv[usAmmoSlot2][0]->data.ubShotsLeft > 0 )
|
||||
{
|
||||
pObjExtMag = &(pTeamSoldier->inv[usAmmoSlot2]);
|
||||
return( pObjExtMag );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return( pObjExtMag );
|
||||
}
|
||||
|
||||
BOOLEAN DeductBulletViaExternalFeeding(SOLDIERTYPE* pSoldier, OBJECTTYPE * pObject)
|
||||
{
|
||||
if ( !pObject || !(pObject->exists()) || !pSoldier || !pSoldier->bActive || !pSoldier->bInSector )
|
||||
// how did we even get here?
|
||||
return false;
|
||||
|
||||
OBJECTTYPE* pObjExtMag = GetExternalFeedingObject(pSoldier, pObject);
|
||||
|
||||
if ( pObjExtMag && (*pObjExtMag)[0]->data.ubShotsLeft != 0 )
|
||||
{
|
||||
(*pObjExtMag)[0]->data.ubShotsLeft--;
|
||||
|
||||
if ( (*pObjExtMag)[0]->data.ubShotsLeft == 0 )
|
||||
{
|
||||
DeleteObj( pObjExtMag );
|
||||
}
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
return( FALSE );
|
||||
}
|
||||
@@ -468,4 +468,14 @@ BOOLEAN HasItemFlag( UINT16 usItem, UINT32 aFlag );
|
||||
// Flugente: get first item number that has this flag. Use with caution, as we search in all items
|
||||
BOOLEAN GetFirstItemWithFlag( UINT16* pusItem, UINT32 aFlag );
|
||||
|
||||
// Flugente: check if this object is currently fed from an external source (belts in inventory, other mercs)
|
||||
BOOLEAN ObjectIsBeingFedExternal(SOLDIERTYPE* pSoldier, OBJECTTYPE * pObject);
|
||||
|
||||
// is this object currently used to feed an externally fed object? This can be in our or someone else's inventory
|
||||
BOOLEAN ObjectIsExternalFeeder(SOLDIERTYPE* pSoldier, OBJECTTYPE * pObject);
|
||||
|
||||
OBJECTTYPE* GetExternalFeedingObject(SOLDIERTYPE* pSoldier, OBJECTTYPE * pObject);
|
||||
|
||||
BOOLEAN DeductBulletViaExternalFeeding(SOLDIERTYPE* pSoldier, OBJECTTYPE * pObject);
|
||||
|
||||
#endif
|
||||
|
||||
+20
-4
@@ -2464,11 +2464,27 @@ void DeductAmmo( SOLDIERTYPE *pSoldier, INT8 bInvPos )
|
||||
// Flugente: check for underbarrel weapons and use that object if necessary
|
||||
OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon( &(pSoldier->inv[bInvPos]) );
|
||||
|
||||
// OK, let's see, don't overrun...
|
||||
if ( (*pObjUsed)[0]->data.gun.ubGunShotsLeft != 0 )
|
||||
// Flugente: external feeding allows us to take ammo from somewhere other than our magazine, like a belt in our inventory our even another mercs
|
||||
if ( gGameExternalOptions.ubExternalFeeding > 0 )
|
||||
{
|
||||
(*pObjUsed)[0]->data.gun.ubGunShotsLeft--;
|
||||
}
|
||||
if ( !DeductBulletViaExternalFeeding(pSoldier, pObj) )
|
||||
{
|
||||
// bullet couldn't be fed externally -> remove bullet from the weapon's magazine
|
||||
// OK, let's see, don't overrun...
|
||||
if ( (*pObjUsed)[0]->data.gun.ubGunShotsLeft != 0 )
|
||||
{
|
||||
(*pObjUsed)[0]->data.gun.ubGunShotsLeft--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// OK, let's see, don't overrun...
|
||||
if ( (*pObjUsed)[0]->data.gun.ubGunShotsLeft != 0 )
|
||||
{
|
||||
(*pObjUsed)[0]->data.gun.ubGunShotsLeft--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( Item[ pObj->usItem ].usItemClass == IC_LAUNCHER || Item[pObj->usItem].cannon || pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO )
|
||||
{
|
||||
|
||||
@@ -13696,6 +13696,276 @@ void SOLDIERTYPE::SoldierInventoryFoodDecay(void)
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: do we currently provide ammo (pAmmoSlot) for someone else's (pubId) gun (pGunSlot)?
|
||||
BOOLEAN SOLDIERTYPE::IsFeedingExternal(UINT8* pubId1, UINT16* pGunSlot1, UINT16* pAmmoSlot1, UINT8* pubId2, UINT16* pGunSlot2, UINT16* pAmmoSlot2)
|
||||
{
|
||||
// make sure we have to check this...
|
||||
if ( gGameExternalOptions.ubExternalFeeding == 0 )
|
||||
return( FALSE );
|
||||
|
||||
// basic check if are up to this task
|
||||
if ( !this->bActive || !this->bInSector || this->stats.bLife < OKLIFE )
|
||||
return( FALSE );
|
||||
|
||||
BOOLEAN isFeeding = FALSE;
|
||||
|
||||
UINT16 usGunItem = 0;
|
||||
UINT8 usGunCalibre = 0;
|
||||
//UINT16 usGunMagSize = 0;
|
||||
UINT8 usGunAmmoType = 0;
|
||||
|
||||
UINT16 usAmmoItem = 0;
|
||||
UINT8 usAmmoCalibre = 0;
|
||||
//UINT16 usAmmoMagSize = 0;
|
||||
UINT8 usAmmoAmmoType = 0;
|
||||
|
||||
UINT16 usMagIndex = 0;
|
||||
|
||||
BOOLEAN firstgunfound = FALSE;
|
||||
|
||||
// do this check for both hands
|
||||
UINT16 firstslot = HANDPOS;
|
||||
UINT16 lastslot = SECONDHANDPOS;
|
||||
for (UINT16 invpos = firstslot; invpos <= lastslot; ++invpos)
|
||||
{
|
||||
// do we have ammo in our hands?
|
||||
OBJECTTYPE* pAmmoObj = &(this->inv[invpos]);
|
||||
|
||||
if ( !pAmmoObj || !(pAmmoObj->exists()) || Item [ pAmmoObj->usItem ].usItemClass != IC_AMMO || (*pAmmoObj)[0]->data.ubShotsLeft <= 0 )
|
||||
// can't use this, end
|
||||
continue;
|
||||
|
||||
usAmmoItem = pAmmoObj->usItem;
|
||||
|
||||
if ( !HasItemFlag( usAmmoItem, AMMO_BELT ) )
|
||||
continue;
|
||||
|
||||
usMagIndex = Item[usAmmoItem].ubClassIndex;
|
||||
|
||||
usAmmoCalibre = Magazine[usMagIndex].ubCalibre;
|
||||
//usAmmoMagSize = Magazine[usMagIndex].ubMagSize;
|
||||
usAmmoAmmoType = Magazine[usMagIndex].ubAmmoType;
|
||||
|
||||
// our current stance is important
|
||||
UINT8 usOurStance = gAnimControl[ this->usAnimState ].ubEndHeight;
|
||||
|
||||
// we will check wether one of our teammates is on the gridno we face
|
||||
INT32 nextGridNoinSight = NewGridNo( this->sGridNo, DirectionInc( this->ubDirection ) );
|
||||
|
||||
SOLDIERTYPE* pTeamSoldier = NULL;
|
||||
INT32 cnt = gTacticalStatus.Team[ this->bTeam ].bFirstID;
|
||||
INT32 lastid = gTacticalStatus.Team[ this->bTeam ].bLastID;
|
||||
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt < lastid; ++cnt, ++pTeamSoldier)
|
||||
{
|
||||
// we ourselves don't count, we can't face ourselves
|
||||
//if ( cnt == this->ubID )
|
||||
//continue;
|
||||
|
||||
// check if teamsoldier exists in this sector
|
||||
if ( !pTeamSoldier || !pTeamSoldier->bActive || !pTeamSoldier->bInSector || pTeamSoldier->sSectorX != this->sSectorX || pTeamSoldier->sSectorY != this->sSectorY || pTeamSoldier->bSectorZ != this->bSectorZ )
|
||||
continue;
|
||||
|
||||
// check if both soldiers are on the same level
|
||||
if ( this->pathing.bLevel != pTeamSoldier->pathing.bLevel )
|
||||
continue;
|
||||
|
||||
// determine wether we can physically provide ammo to our teammate.
|
||||
// check the stance, prone on standing (both ways) doesn't work
|
||||
if ( usOurStance == ANIM_STAND )
|
||||
{
|
||||
if ( gAnimControl[ pTeamSoldier->usAnimState ].ubEndHeight != ANIM_STAND && gAnimControl[ pTeamSoldier->usAnimState ].ubEndHeight != ANIM_CROUCH )
|
||||
continue;
|
||||
}
|
||||
else if ( usOurStance == ANIM_PRONE )
|
||||
{
|
||||
if ( gAnimControl[ pTeamSoldier->usAnimState ].ubEndHeight != ANIM_PRONE && gAnimControl[ pTeamSoldier->usAnimState ].ubEndHeight != ANIM_CROUCH )
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if we look at our teammate, or look the same way he does, or in the direction between
|
||||
BOOLEAN fPositioningOkay = FALSE;
|
||||
// the other person must be near
|
||||
if ( SpacesAway(this->sGridNo, pTeamSoldier->sGridNo) == 0 )
|
||||
{
|
||||
// same tile -> its ourself -> ok
|
||||
fPositioningOkay = TRUE;
|
||||
}
|
||||
else if ( SpacesAway(this->sGridNo, pTeamSoldier->sGridNo) == 1 )
|
||||
{
|
||||
// we look at him -> ok
|
||||
if ( nextGridNoinSight == pTeamSoldier->sGridNo )
|
||||
fPositioningOkay = TRUE;
|
||||
else
|
||||
{
|
||||
// if we look at the same tile, then that's okay too
|
||||
INT32 teamsoldiernextGridNoinSight = NewGridNo( pTeamSoldier->sGridNo, DirectionInc( pTeamSoldier->ubDirection ) );
|
||||
|
||||
if ( nextGridNoinSight == teamsoldiernextGridNoinSight )
|
||||
fPositioningOkay = TRUE;
|
||||
else
|
||||
{
|
||||
// if we both look in the same direction...
|
||||
INT8 teammatedirection = pTeamSoldier->ubDirection;
|
||||
INT8 ourdirection = this->ubDirection;
|
||||
|
||||
if ( teammatedirection == ourdirection )
|
||||
{
|
||||
// if the angle between our teammates sightline and the direct line from us to him is 90 degrees, then we are also able to supply
|
||||
INT8 ourrightdirection = (ourdirection + 2) % NUM_WORLD_DIRECTIONS;
|
||||
INT8 ourleftdirection = (ourdirection - 2) % NUM_WORLD_DIRECTIONS;
|
||||
|
||||
if ( NewGridNo( this->sGridNo, DirectionInc( ourrightdirection ) ) == pTeamSoldier->sGridNo || NewGridNo( this->sGridNo, DirectionInc( ourleftdirection ) ) == pTeamSoldier->sGridNo )
|
||||
fPositioningOkay = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !fPositioningOkay )
|
||||
continue;
|
||||
|
||||
// ok, we are facing a teammate. Check if he has a gun in any hand that still has ammo left
|
||||
UINT16 pTeamSoldierfirstslot = HANDPOS;
|
||||
UINT16 pTeamSoldierlastslot = SECONDHANDPOS;
|
||||
for (UINT16 teamsoldierinvpos = pTeamSoldierfirstslot; teamsoldierinvpos <= pTeamSoldierlastslot; ++teamsoldierinvpos)
|
||||
{
|
||||
OBJECTTYPE* pObjInHands = &(pTeamSoldier->inv[teamsoldierinvpos]);
|
||||
if ( pObjInHands && pObjInHands->exists() && Item [ pObjInHands->usItem ].usItemClass == IC_GUN && (HasItemFlag( pObjInHands->usItem, BELT_FED ) || HasAttachmentOfClass(pObjInHands, AC_FEEDER) ) && (*pObjInHands)[0]->data.gun.ubGunShotsLeft > 0 )
|
||||
{
|
||||
// remember the caliber, magsize (TODO: really?) and type of ammo. They all have to fit
|
||||
usGunItem = pObjInHands->usItem;
|
||||
|
||||
usGunCalibre = Weapon[usGunItem].ubCalibre;
|
||||
//usGunMagSize = Weapon[usGunItem].ubMagSize;
|
||||
usGunAmmoType = (*pObjInHands)[0]->data.gun.ubGunAmmoType;
|
||||
|
||||
if ( usGunCalibre == usAmmoCalibre && /*usGunMagSize == usAmmoMagSize &&*/ usGunAmmoType == usAmmoAmmoType )
|
||||
{
|
||||
// same calibre, same magsize, same ammotype. We can serve this guy
|
||||
if ( !firstgunfound )
|
||||
{
|
||||
firstgunfound = TRUE;
|
||||
(*pubId1) = cnt;
|
||||
(*pGunSlot1) = teamsoldierinvpos;
|
||||
(*pAmmoSlot1) = invpos;
|
||||
isFeeding = TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*pubId2) = cnt;
|
||||
(*pGunSlot2) = teamsoldierinvpos;
|
||||
(*pAmmoSlot2) = invpos;
|
||||
isFeeding = TRUE;
|
||||
|
||||
// we really found a second gun. we can only serve 2 guns maximum. lets end this
|
||||
return( isFeeding );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we reach this point, the only soldier that we could reach doesn't fit -> stop this search
|
||||
//break;
|
||||
}
|
||||
}
|
||||
|
||||
// if set to 1, we do not wether we feed ourself from our inventory
|
||||
if ( gGameExternalOptions.ubExternalFeeding < 2 )
|
||||
return( isFeeding );
|
||||
|
||||
// if we reach this point, we have checked all our teammates, and we do not provide external feeding for any of them
|
||||
// it is possible that we provide external feeding for OURSELF (think of ammo belts in a dedicated LBE slot, or of a gun that requires a separate energy source)
|
||||
// first, determine wether we need external feeding for our gun. We do this for both hands, as it is thinkable that someone has 2 one-handed guns with external feeding
|
||||
|
||||
// this determines which slots we'll search for ammo
|
||||
UINT16 firstslotforammo = MEDPOCK1POS;
|
||||
UINT16 lastslotforammo = MEDPOCK2POS;
|
||||
|
||||
// for robots and AI-controlled soldiers (who don't have any LBE gear), we put a change in here so that ALL their slots are checked for ammo
|
||||
if ( this->bTeam != gbPlayerNum || MercPtrs[ this->ubID ]->flags.uiStatusFlags & SOLDIER_ROBOT )
|
||||
{
|
||||
firstslotforammo = HANDPOS;
|
||||
lastslotforammo = NUM_INV_SLOTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// as a merc, the only slots that are valid for external feeding are the 2 medium-sized slots on a vest (because I say so). And that only if the vest is allowed to do that, which we will now check:
|
||||
if ( !(this->inv[VESTPOCKPOS].exists()) || !HasItemFlag( this->inv[VESTPOCKPOS].usItem, AMMO_BELT_VEST ) )
|
||||
return( isFeeding );
|
||||
}
|
||||
|
||||
UINT16 searchgunfirstslot = HANDPOS;
|
||||
UINT16 searchgunlastslot = SECONDHANDPOS;
|
||||
for (UINT16 invpos = searchgunfirstslot; invpos <= searchgunlastslot; ++invpos)
|
||||
{
|
||||
// check our hands for guns
|
||||
OBJECTTYPE* pObj = &(this->inv[invpos]);
|
||||
|
||||
UINT16 usGunItem = pObj->usItem;
|
||||
|
||||
if ( !pObj || !(pObj->exists()) || Item [usGunItem ].usItemClass != IC_GUN || !(HasItemFlag( usGunItem, BELT_FED ) || HasAttachmentOfClass(pObj, AC_FEEDER) ) || (*pObj)[0]->data.gun.ubGunShotsLeft <= 0 )
|
||||
// can't use this, end
|
||||
continue;
|
||||
|
||||
// remember the caliber, magsize (TODO: really?) and type of ammo. They all have to fit
|
||||
usGunCalibre = Weapon[usGunItem].ubCalibre;
|
||||
//usGunMagSize = Weapon[usGunItem].ubMagSize;
|
||||
usGunAmmoType = (*pObj)[0]->data.gun.ubGunAmmoType;
|
||||
|
||||
// now check the inventory for an ammo belt. If we are not from the player team or a robot, we will search the entire inventory
|
||||
for ( UINT16 bLoop = firstslotforammo; bLoop <= lastslotforammo; ++bLoop)
|
||||
{
|
||||
if (this->inv[bLoop].exists() == true )
|
||||
{
|
||||
OBJECTTYPE * pAmmoObj = &(this->inv[bLoop]); // ... get pointer for this item ...
|
||||
|
||||
if ( pAmmoObj != NULL ) // ... if pointer is not obviously useless ...
|
||||
{
|
||||
if ( pAmmoObj->ubNumberOfObjects == 1 )
|
||||
{
|
||||
usAmmoItem = pAmmoObj->usItem;
|
||||
|
||||
if ( Item [ usAmmoItem ].usItemClass == IC_AMMO && HasItemFlag( usAmmoItem, AMMO_BELT ) )
|
||||
{
|
||||
// remember the caliber, magsize (TODO: really?) and type of ammo. They all have to fit
|
||||
usMagIndex = Item[usAmmoItem].ubClassIndex;
|
||||
usAmmoCalibre = Magazine[usMagIndex].ubCalibre;
|
||||
//usAmmoMagSize = Magazine[usMagIndex].ubMagSize;
|
||||
usAmmoAmmoType = Magazine[usMagIndex].ubAmmoType;
|
||||
|
||||
if ( usGunCalibre == usAmmoCalibre && /*usGunMagSize == usAmmoMagSize &&*/ usGunAmmoType == usAmmoAmmoType )
|
||||
{
|
||||
// same calibre, same magsize, same ammotype. We can serve this guy
|
||||
if ( !firstgunfound )
|
||||
{
|
||||
firstgunfound = TRUE;
|
||||
(*pubId1) = this->ubID;
|
||||
(*pGunSlot1) = invpos;
|
||||
(*pAmmoSlot1) = bLoop;
|
||||
isFeeding = TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*pubId2) = this->ubID;
|
||||
(*pGunSlot2) = invpos;
|
||||
(*pAmmoSlot2) = bLoop;
|
||||
isFeeding = TRUE;
|
||||
|
||||
// we really found a second gun. we can only serve 2 guns maximum. lets end this
|
||||
return( isFeeding );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return( isFeeding );
|
||||
}
|
||||
|
||||
INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
|
||||
@@ -1436,6 +1436,9 @@ public:
|
||||
|
||||
// Flugente: Food decay in inventory
|
||||
void SoldierInventoryFoodDecay( void );
|
||||
|
||||
// Flugente: do we currently provide ammo (pAmmoSlot) for someone else's (pubId) gun (pGunSlot)?
|
||||
BOOLEAN IsFeedingExternal(UINT8* pubId1, UINT16* pGunSlot1, UINT16* pAmmoSlot1, UINT8* pubId2, UINT16* pGunSlot2, UINT16* pAmmoSlot2);
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}; // SOLDIERTYPE;
|
||||
|
||||
Reference in New Issue
Block a user