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:
Flugente
2012-07-23 19:31:27 +00:00
parent c265a63b28
commit fe460b0325
10 changed files with 492 additions and 16 deletions
+9 -7
View File
@@ -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 ##################
+3
View File
@@ -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;
+15
View File
@@ -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 )
{
+32
View File
@@ -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 );
}
}
}
+5 -5
View File
@@ -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
+125
View File
@@ -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 );
}
+10
View File
@@ -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
View File
@@ -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 )
{
+270
View File
@@ -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 )
{
+3
View File
@@ -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;