mirror of
https://github.com/1dot13/source.git
synced 2026-08-05 14:00:23 +02:00
- New Feature: Allow attaching and using underbarrel weapons (by Flugente & JMich)
o You can now attach weapons to other weapons (only one at a time). Comes with additional fire modes (by cycling in tactical with key 'b') o A new item, the KAC masterkey, demonstrates this. Raider and Kelly have one in their starting kit 4. (pics by smeagol) o works both in OCTh and NCTH. Aiming is done via the main gun, but all physical values of the attached gun are considered. o reload an underbarrel gun while it is attached by dropping the ammo on the main gun while an underbarrel fire mode is active. Cycle firemodes in tactical by pressing 'b' o Attachments to underbarrel weapons are inseparable while weapon is attached, but they do work. - Overheating weapons additions (by Flugente) o New option OVERHEATING_DISPLAY_THERMOMETER_RED_OFFSET controls how red the temperature bar is at the beginning. o New option OVERHEATING_SET_ZERO_UPON_NEW_SECTOR sets temperature of items on the floor to zero if loading a new sector git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5133 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+176
-13
@@ -3587,7 +3587,9 @@ INT8 FindAmmoToReload( SOLDIERTYPE * pSoldier, INT8 bWeaponIn, INT8 bExcludeSlot
|
||||
{
|
||||
return( NO_SLOT );
|
||||
}
|
||||
pObj = &(pSoldier->inv[bWeaponIn]);
|
||||
|
||||
// Flugente: check for underbarrel weapons and use that object if necessary
|
||||
pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[bWeaponIn]) );
|
||||
|
||||
//<SB> manual recharge
|
||||
if ((*pObj)[0]->data.gun.ubGunShotsLeft && !((*pObj)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER) )
|
||||
@@ -3656,7 +3658,9 @@ BOOLEAN AutoReload( SOLDIERTYPE * pSoldier )
|
||||
BOOLEAN fRet;
|
||||
|
||||
CHECKF( pSoldier );
|
||||
pObj = &(pSoldier->inv[HANDPOS]);
|
||||
|
||||
// Flugente: check for underbarrel weapons and use that object if necessary
|
||||
pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[HANDPOS]) );
|
||||
|
||||
//<SB> manual recharge
|
||||
if ((*pObj)[0]->data.gun.ubGunShotsLeft && !((*pObj)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER) )
|
||||
@@ -3746,7 +3750,9 @@ BOOLEAN AutoReload( SOLDIERTYPE * pSoldier )
|
||||
// then do a reload of both guns!
|
||||
if ( (fRet == TRUE) && pSoldier->IsValidSecondHandShotForReloadingPurposes( ) )
|
||||
{
|
||||
pObj = &(pSoldier->inv[SECONDHANDPOS]);
|
||||
// Flugente: check for underbarrel weapons and use that object if necessary
|
||||
pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[SECONDHANDPOS]) );
|
||||
|
||||
bSlot = FindAmmoToReload( pSoldier, SECONDHANDPOS, NO_SLOT );
|
||||
if (bSlot != NO_SLOT)
|
||||
{
|
||||
@@ -4612,7 +4618,9 @@ BOOLEAN OBJECTTYPE::AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttac
|
||||
{
|
||||
//Make sure it's actually on that gun..
|
||||
//if(FindAttachment_GrenadeLauncher(this)->usItem == attachmentObject.usItem){
|
||||
if(FindAttachment(this, attachmentObject.usItem, subObject)->usItem == attachmentObject.usItem){
|
||||
// Flugente: if we attach a gun to another gun, do not transfer attachments
|
||||
if( Item[attachmentObject.usItem].usItemClass != IC_GUN && FindAttachment(this, attachmentObject.usItem, subObject)->usItem == attachmentObject.usItem)
|
||||
{
|
||||
// transfer the grenade from the grenade launcher to the gun
|
||||
|
||||
//To know wether this grenade is valid, we need to correct the slots, because they may have changed when attaching the UGL
|
||||
@@ -5861,7 +5869,10 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
|
||||
case IC_GUN:
|
||||
if (Item[pObj->usItem].usItemClass == IC_AMMO)
|
||||
{
|
||||
if (Weapon[pInSlot->usItem].ubCalibre == Magazine[Item[pObj->usItem].ubClassIndex].ubCalibre)
|
||||
// Flugente: if we have an underbarrel weapon, we can reload that
|
||||
OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon(pInSlot);
|
||||
|
||||
if (Weapon[pObjUsed->usItem].ubCalibre == Magazine[Item[pObj->usItem].ubClassIndex].ubCalibre)
|
||||
{
|
||||
//CHRISL: Work differently with ammo crates but only when not in combat
|
||||
if(Magazine[Item[pObj->usItem].ubClassIndex].ubMagType >= AMMO_BOX)
|
||||
@@ -5881,7 +5892,7 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
|
||||
{
|
||||
if(Item[loop].usItemClass == IC_AMMO)
|
||||
{
|
||||
if(Magazine[Item[loop].ubClassIndex].ubCalibre == Weapon[pInSlot->usItem].ubCalibre && Magazine[Item[loop].ubClassIndex].ubAmmoType == Magazine[Item[pObj->usItem].ubClassIndex].ubAmmoType && Magazine[Item[loop].ubClassIndex].ubMagSize == GetMagSize(pInSlot))
|
||||
if(Magazine[Item[loop].ubClassIndex].ubCalibre == Weapon[pObjUsed->usItem].ubCalibre && Magazine[Item[loop].ubClassIndex].ubAmmoType == Magazine[Item[pObj->usItem].ubClassIndex].ubAmmoType && Magazine[Item[loop].ubClassIndex].ubMagSize == GetMagSize(pObjUsed))
|
||||
newItem = loop;
|
||||
}
|
||||
}
|
||||
@@ -5891,7 +5902,7 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
|
||||
ubShotsLeft = (*pObj)[0]->data.ubShotsLeft;
|
||||
for(UINT8 clip = 0; clip < 5; clip++)
|
||||
{
|
||||
magSize = GetMagSize(pInSlot);
|
||||
magSize = GetMagSize(pObjUsed);
|
||||
if(ubShotsLeft < magSize)
|
||||
magSize = ubShotsLeft;
|
||||
if(CreateAmmo(newItem, &tempClip, magSize))
|
||||
@@ -5963,7 +5974,7 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
|
||||
}
|
||||
}
|
||||
else
|
||||
return( ReloadGun( pSoldier, pInSlot, pObj ) );
|
||||
return( ReloadGun( pSoldier, pObjUsed, pObj ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -7470,6 +7481,24 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE* pAttachment, OBJECTTYPE * pNew
|
||||
}
|
||||
}
|
||||
|
||||
// if in attached weapon mode and don't have weapon with GL attached in hand, reset weapon mode
|
||||
if ( ( (pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO )&& !IsGrenadeLauncherAttached( &(pSoldier->inv[ HANDPOS ]) ) ) ||
|
||||
( (pSoldier->bWeaponMode == WM_ATTACHED_UB || pSoldier->bWeaponMode == WM_ATTACHED_UB_BURST || pSoldier->bWeaponMode == WM_ATTACHED_UB_AUTO )&& !IsUnderBarrelAttached( &(pSoldier->inv[ HANDPOS ] ) ) ) )
|
||||
{
|
||||
if ( !Weapon[pSoldier->inv[ HANDPOS ].usItem].NoSemiAuto )
|
||||
{
|
||||
pSoldier->bWeaponMode = WM_NORMAL;
|
||||
pSoldier->bDoBurst = FALSE;
|
||||
pSoldier->bDoAutofire = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSoldier->bWeaponMode = WM_AUTOFIRE;
|
||||
pSoldier->bDoBurst = TRUE;
|
||||
pSoldier->bDoAutofire = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(Item[this->usItem].usItemClass == IC_GUN && oldMagSize != GetMagSize(this, subObject)){
|
||||
fInterfacePanelDirty = DIRTYLEVEL2;
|
||||
RenderBulletIcon(this, subObject);
|
||||
@@ -9477,9 +9506,13 @@ void GetRecoil( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 *bRecoilX, INT8 *b
|
||||
{
|
||||
*bRecoilX = 0;
|
||||
*bRecoilY = 0;
|
||||
|
||||
// Flugente: get weapon actually used (might be an underbarrel shotgun)
|
||||
OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon(pObj);
|
||||
OBJECTTYPE* pObjUsedInHand = pSoldier->GetUsedWeapon( &(pSoldier->inv[HANDPOS]) );
|
||||
|
||||
//if (ubNumBullet < 2)
|
||||
if (ubNumBullet < Weapon[pObj->usItem].ubRecoilDelay)
|
||||
if (ubNumBullet < Weapon[pObjUsed->usItem].ubRecoilDelay)
|
||||
{
|
||||
// The first bullet in a volley never has recoil - it hasn't "set in" yet. Only the second+ bullets
|
||||
// will have any recoil.
|
||||
@@ -9488,13 +9521,15 @@ void GetRecoil( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 *bRecoilX, INT8 *b
|
||||
return;
|
||||
}
|
||||
|
||||
*bRecoilX = Weapon[pObj->usItem].bRecoilX;
|
||||
*bRecoilY = Weapon[pObj->usItem].bRecoilY;
|
||||
*bRecoilX = Weapon[pObjUsed->usItem].bRecoilX;
|
||||
*bRecoilY = Weapon[pObjUsed->usItem].bRecoilY;
|
||||
|
||||
// Apply a percentage-based modifier. This can increase or decrease BOTH axes. At most, it can eliminate
|
||||
// recoil on the gun.
|
||||
|
||||
INT16 sPercentRecoilModifier = GetPercentRecoilModifier( pObj );
|
||||
//INT16 sPercentRecoilModifier = GetPercentRecoilModifier( pObj );
|
||||
INT16 sPercentRecoilModifier = __max(-100, (GetBasePercentRecoilModifier( pObjUsed ) + GetAttachmentPercentRecoilModifier( pObjUsedInHand ) ));
|
||||
|
||||
|
||||
*bRecoilX += (*bRecoilX * sPercentRecoilModifier ) / 100;
|
||||
*bRecoilY += (*bRecoilY * sPercentRecoilModifier ) / 100;
|
||||
@@ -9505,7 +9540,10 @@ void GetRecoil( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 *bRecoilX, INT8 *b
|
||||
INT8 bRecoilAdjustX = 0;
|
||||
INT8 bRecoilAdjustY = 0;
|
||||
|
||||
GetFlatRecoilModifier( pObj, &bRecoilAdjustX, &bRecoilAdjustY );
|
||||
//GetFlatRecoilModifier( pObj, &bRecoilAdjustX, &bRecoilAdjustY );
|
||||
GetBaseFlatRecoilModifier( pObj, &bRecoilAdjustX, &bRecoilAdjustY );
|
||||
GetAttachmentFlatRecoilModifier( &pSoldier->inv[HANDPOS], &bRecoilAdjustX, &bRecoilAdjustY);
|
||||
//JMich TODO: Currently no check for dual wielding
|
||||
|
||||
*bRecoilX = __max(0, *bRecoilX + bRecoilAdjustX);
|
||||
*bRecoilY = __max(0, *bRecoilY + bRecoilAdjustY);
|
||||
@@ -9517,6 +9555,44 @@ void GetRecoil( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 *bRecoilX, INT8 *b
|
||||
// HEADROCK HAM 4: This function calculates the flat recoil adjustment for a gun. Flat adjustment increases
|
||||
// or decreases recoil by a specific number of points in either the vertical or horizontal axes (or both).
|
||||
// It can potentially cause a weapon it reverse its recoil direction.
|
||||
void GetBaseFlatRecoilModifier( OBJECTTYPE *pObj, INT8 *bRecoilModifierX, INT8 *bRecoilModifierY )
|
||||
{
|
||||
INT8 bRecoilAdjustX = 0;
|
||||
INT8 bRecoilAdjustY = 0;
|
||||
if (pObj->exists() == true && UsingNewCTHSystem() == true)
|
||||
{
|
||||
// Inherent item modifiers
|
||||
bRecoilAdjustX += BonusReduceMore( Item[pObj->usItem].RecoilModifierX, (*pObj)[0]->data.objectStatus );
|
||||
bRecoilAdjustY += BonusReduceMore( Item[pObj->usItem].RecoilModifierY, (*pObj)[0]->data.objectStatus );
|
||||
|
||||
// Ammo item modifiers
|
||||
bRecoilAdjustX += Item[(*pObj)[0]->data.gun.usGunAmmoItem].RecoilModifierX;
|
||||
bRecoilAdjustY += Item[(*pObj)[0]->data.gun.usGunAmmoItem].RecoilModifierY;
|
||||
}
|
||||
|
||||
*bRecoilModifierX = bRecoilAdjustX;
|
||||
*bRecoilModifierY = bRecoilAdjustY;
|
||||
}
|
||||
void GetAttachmentFlatRecoilModifier( OBJECTTYPE *pObj, INT8 *bRecoilModifierX, INT8 *bRecoilModifierY )
|
||||
{
|
||||
INT8 bRecoilAdjustX = 0;
|
||||
INT8 bRecoilAdjustY = 0;
|
||||
if (pObj->exists() == true && UsingNewCTHSystem() == true)
|
||||
{
|
||||
// Attachment item modifiers
|
||||
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
|
||||
{
|
||||
if (iter->exists())
|
||||
{
|
||||
bRecoilAdjustX += BonusReduceMore( Item[iter->usItem].RecoilModifierX, (*iter)[0]->data.objectStatus );
|
||||
bRecoilAdjustY += BonusReduceMore( Item[iter->usItem].RecoilModifierY, (*iter)[0]->data.objectStatus );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*bRecoilModifierX += bRecoilAdjustX;
|
||||
*bRecoilModifierY += bRecoilAdjustY;
|
||||
}
|
||||
void GetFlatRecoilModifier( OBJECTTYPE *pObj, INT8 *bRecoilModifierX, INT8 *bRecoilModifierY )
|
||||
{
|
||||
|
||||
@@ -9553,6 +9629,39 @@ void GetFlatRecoilModifier( OBJECTTYPE *pObj, INT8 *bRecoilModifierX, INT8 *bRec
|
||||
// This adjustment either increases or decreases the gun's vertical and horizontal recoil at the same time. Due to
|
||||
// the percentage-based nature of this modifier, it cannot cause a gun to reverse its recoil - only diminish it to
|
||||
// zero.
|
||||
INT16 GetBasePercentRecoilModifier( OBJECTTYPE *pObj)
|
||||
{
|
||||
INT16 sRecoilAdjust = 0;
|
||||
|
||||
if (pObj->exists() == true && UsingNewCTHSystem() == true)
|
||||
{
|
||||
// Inherent item modifiers
|
||||
sRecoilAdjust += BonusReduceMore( Item[pObj->usItem].PercentRecoilModifier, (*pObj)[0]->data.objectStatus );
|
||||
|
||||
// Ammo item modifiers
|
||||
sRecoilAdjust += Item[(*pObj)[0]->data.gun.usGunAmmoItem].PercentRecoilModifier;
|
||||
}
|
||||
|
||||
return (sRecoilAdjust);
|
||||
}
|
||||
INT16 GetAttachmentPercentRecoilModifier( OBJECTTYPE *pObj)
|
||||
{
|
||||
INT16 sRecoilAdjust = 0;
|
||||
|
||||
if (pObj->exists() == true && UsingNewCTHSystem() == true)
|
||||
{
|
||||
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
|
||||
{
|
||||
if (iter->exists())
|
||||
{
|
||||
sRecoilAdjust += BonusReduceMore( Item[iter->usItem].PercentRecoilModifier, (*iter)[0]->data.objectStatus );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (sRecoilAdjust);
|
||||
|
||||
}
|
||||
INT16 GetPercentRecoilModifier( OBJECTTYPE *pObj )
|
||||
{
|
||||
INT16 sRecoilAdjust = 0;
|
||||
@@ -10550,6 +10659,60 @@ UINT16 GetAttachedGrenadeLauncher( OBJECTTYPE * pObj )
|
||||
return( NONE );
|
||||
}
|
||||
|
||||
UINT16 GetAttachedUnderBarrel( OBJECTTYPE * pObj )
|
||||
{
|
||||
if (pObj->exists() == true) {
|
||||
|
||||
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
|
||||
if ((Item[iter->usItem].usItemClass & (IC_GUN | IC_BLADE) ) && iter->exists())
|
||||
{
|
||||
return( (UINT16) Item[iter->usItem].uiIndex );
|
||||
}
|
||||
}
|
||||
}
|
||||
return( NONE );
|
||||
}
|
||||
BOOLEAN IsUnderBarrelAttached( OBJECTTYPE * pObj, UINT8 subObject )
|
||||
{
|
||||
if (pObj->exists() == true) {
|
||||
|
||||
for (attachmentList::iterator iter = (*pObj)[subObject]->attachments.begin(); iter != (*pObj)[subObject]->attachments.end(); ++iter) {
|
||||
if (Item[iter->usItem].usItemClass & (IC_GUN | IC_BLADE) && iter->exists() )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
OBJECTTYPE* FindAttachment_UnderBarrel( OBJECTTYPE * pObj )
|
||||
{
|
||||
if (pObj->exists() == true) {
|
||||
|
||||
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
|
||||
if (Item[iter->usItem].usItemClass & (IC_GUN | IC_BLADE) && iter->exists() )
|
||||
{
|
||||
return( &(*iter) );
|
||||
}
|
||||
}
|
||||
}
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
INT16 GetUnderBarrelStatus( OBJECTTYPE * pObj )
|
||||
{
|
||||
if (pObj->exists() == true) {
|
||||
|
||||
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
|
||||
if (Item[iter->usItem].usItemClass & (IC_GUN | IC_BLADE) && iter->exists())
|
||||
{
|
||||
return( (*iter)[0]->data.objectStatus );
|
||||
}
|
||||
}
|
||||
}
|
||||
return( ITEM_NOT_FOUND );
|
||||
}
|
||||
|
||||
INT16 GetAttachedArmourBonus( OBJECTTYPE * pObj )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user