Bugfixes (by Flugente)

- fixed a bug that prevented zombies from rising in turnbased mode
- fixed a bug that prevented weapons on the floor from cooling down in turnbased mode
- fixed a bug that caused gun traps with buckshot ammo to deduct to much ammo
- fixed a bug that could crash the game when firing a lot of gun traps at the same time

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5346 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2012-06-16 22:57:53 +00:00
parent 99d9567f35
commit 88155e52d0
11 changed files with 272 additions and 246 deletions
+7 -15
View File
@@ -1133,6 +1133,13 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
{
return( ITEM_HANDLE_REFUSAL );
}
// we can only do this on certain terraintypes
INT8 bOverTerrainType = GetTerrainType( sGridNo );
if( bOverTerrainType != FLAT_GROUND && bOverTerrainType != DIRT_ROAD && bOverTerrainType != LOW_GRASS )
{
return( ITEM_HANDLE_REFUSAL );
}
}
// if we have a shovel in our hands, the targetted gridno must be a fortification (debris will do for this check)
@@ -5982,8 +5989,6 @@ void SoldierStealItemFromSoldier( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent,
SetCustomizableTimerCallbackAndDelay( 1000, CheckForPickedOwnership, TRUE );
}
extern UINT8 NumEnemiesInAnySector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ );
BOOLEAN BuildFortification( UINT32 flag )
{
INT32 sGridNo;
@@ -5997,19 +6002,6 @@ BOOLEAN BuildFortification( UINT32 flag )
if ( gusSelectedSoldier == NOBODY )
return FALSE;
// comment this in to forbid building while enemies are around
/*if( (gTacticalStatus.uiFlags & INCOMBAT) && (gTacticalStatus.uiFlags & TURNBASED) )
{
return FALSE;
}
if( gWorldSectorX != -1 && gWorldSectorY != -1 && gWorldSectorX != 0 && gWorldSectorY != 0 &&
NumEnemiesInAnySector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) > 0 )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Cannot build while enemies are in this sector" );
return FALSE;
}*/
if( gbWorldSectorZ > 0 || gsInterfaceLevel > 0)
{
return FALSE;
+121 -122
View File
@@ -5693,132 +5693,131 @@ INT8 FireBulletGivenTargetTrapOnly( SOLDIERTYPE* pThrower, OBJECTTYPE* pObj, INT
pBullet->fTracer = FALSE;
}
}*/
///////////////////////// SOUND ////////////////////////////
//PLAY SOUND
// ( For throwing knife.. it's earlier in the animation
if ( Weapon[ pObj->usItem ].sSound != 0 && Item[ pObj->usItem ].usItemClass != IC_THROWING_KNIFE )
{
// Switch on silencer...
UINT16 noisefactor = GetPercentNoiseVolume( pObj );
if( noisefactor < MAX_PERCENT_NOISE_VOLUME_FOR_SILENCED_SOUND || Weapon[ pObj->usItem ].ubAttackVolume <= 10 )
{
INT32 uiSound;
uiSound = Weapon [ pObj->usItem ].silencedSound;
PlayJA2Sample( uiSound, RATE_11025, SoundVolume( HIGHVOLUME, gridno ), 1, SoundDir( gridno ) );
}
else
{
INT8 volume = HIGHVOLUME;
if ( noisefactor < 100 ) volume = (volume * noisefactor) / 100;
PlayJA2Sample( Weapon[ pObj->usItem ].sSound, RATE_11025, SoundVolume( volume, gridno ), 1, SoundDir( gridno ) );
}
}
///////////////////////// SOUND ////////////////////////////
// deduct ammo
(*pObj)[0]->data.gun.ubGunShotsLeft = max(0, (*pObj)[0]->data.gun.ubGunShotsLeft - 1);
//gTacticalStatus.ubAttackBusyCount++;
if(is_client)send_bullet( pBullet, pObj->usItem );
FireBullet( pThrower, pBullet, FALSE );
///////////////////////// SOUND ////////////////////////////
UINT8 ubVolume = Weapon[ pObj->usItem ].ubAttackVolume;
// Snap: get cumulative noise reduction from the weapon and its attachments
UINT16 noisefactor = GetPercentNoiseVolume( pObj );
if ( ubVolume * noisefactor > 25000 )
{ // Snap: hack this to prevent overflow (damn miserly programmers!)
ubVolume = 250;
}
else
{
ubVolume = __max( 1, ( ubVolume * GetPercentNoiseVolume( pObj ) ) / 100 );
}
MakeNoise( NOBODY, gridno, 0, pThrower->bOverTerrainType, ubVolume, NOISE_GUNFIRE );
///////////////////////// SOUND ////////////////////////////
///////////////////////// OVERHEATING AND STATUS REDUCTION ////////////////////////////
INT16 iOverheatReliabilityMalus = 0;
// Flugente: Increase Weapon Temperature
if ( gGameOptions.fWeaponOverheating )
{
FLOAT overheatjampercentage = GetGunOverheatDamagePercentage( pObj ); // ... how much above the gun's usOverheatingDamageThreshold are we? ...
if ( overheatjampercentage > 1.0 )
iOverheatReliabilityMalus = (INT16)floor(overheatjampercentage*overheatjampercentage);
GunIncreaseHeat( pObj );
}
// Flugente : Added a malus to reliability for overheated guns
// HEADROCK HAM 5: Variable NCTH base change
UINT32 uiDepreciateTest = 0;
if ( UsingNewCTHSystem() == true)
{
UINT16 usBaseChance = gGameCTHConstants.BASIC_RELIABILITY_ODDS;
FLOAT dReliabilityRatio = 3.0f * ((FLOAT)usBaseChance / (FLOAT)BASIC_DEPRECIATE_CHANCE); // Compare original odds to new odds.
uiDepreciateTest = usBaseChance + (INT16)( dReliabilityRatio * GetReliability( pObj ) - iOverheatReliabilityMalus);
uiDepreciateTest = max(0, uiDepreciateTest);
}
else
{
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 * GetReliability( pObj ) - iOverheatReliabilityMalus, 0);
}
if ( !PreRandom( uiDepreciateTest ) && ( (*pObj)[0]->data.objectStatus > 1) )
{
(*pObj)[0]->data.objectStatus--;
}
///////////////////////// OVERHEATING AND STATUS REDUCTION ////////////////////////////
///////////////////////// JAMMING ////////////////////////////
// Algorithm for jamming
int maxJamChance = 50; // Externalize this?
int reliability = GetReliability( pObj );
int condition = (*pObj)[0]->data.gun.bGunStatus;
int invertedBaseJamChance = condition + (reliability * 2) - gGameExternalOptions.ubWeaponReliabilityReductionPerRainIntensity * 1;
// Flugente FTW 1: If overheating is allowed, a gun will be prone to more overheating if its temperature is high
if ( gGameOptions.fWeaponOverheating )
{
FLOAT overheatjampercentage = GetGunOverheatJamPercentage( pObj ); // how much above the gun's usOverheatingJamThreshold are we? ...
int overheatjamfactor = (int)(100* overheatjampercentage); // We need an integer value and rough percentages
overheatjamfactor = max(0, overheatjamfactor - 100); // If we haven't reached the OverheatJamThreshold, no increased chance of jamming because of overheating
invertedBaseJamChance -= overheatjamfactor; // lower invertedBaseJamChance (thereby increasing jamChance later on)
}
if (invertedBaseJamChance < 0)
invertedBaseJamChance = 0;
else if (invertedBaseJamChance > 100)
invertedBaseJamChance = 100;
int jamChance = 100 - (int)sqrt((double)invertedBaseJamChance * (75.0 + (double)invertedBaseJamChance / 2.0));
if (jamChance < 0)
jamChance = 0;
else if (jamChance > maxJamChance - reliability)
jamChance = maxJamChance - reliability;
if ((INT32) PreRandom( 100 ) < jamChance )
{
// jam! negate the gun ammo status.
(*pObj)[0]->data.gun.bGunAmmoStatus *= -1;
}
///////////////////////// JAMMING ////////////////////////////
//<SB> manual recharge
if (Weapon[Item[pObj->usItem].ubClassIndex].APsToReloadManually > 0)
(*pObj)[0]->data.gun.ubGunState &= ~GS_CARTRIDGE_IN_CHAMBER;
//<SB>
}
///////////////////////// SOUND ////////////////////////////
//PLAY SOUND
// ( For throwing knife.. it's earlier in the animation
if ( Weapon[ pObj->usItem ].sSound != 0 && Item[ pObj->usItem ].usItemClass != IC_THROWING_KNIFE )
{
// Switch on silencer...
UINT16 noisefactor = GetPercentNoiseVolume( pObj );
if( noisefactor < MAX_PERCENT_NOISE_VOLUME_FOR_SILENCED_SOUND || Weapon[ pObj->usItem ].ubAttackVolume <= 10 )
{
INT32 uiSound;
uiSound = Weapon [ pObj->usItem ].silencedSound;
PlayJA2Sample( uiSound, RATE_11025, SoundVolume( HIGHVOLUME, gridno ), 1, SoundDir( gridno ) );
}
else
{
INT8 volume = HIGHVOLUME;
if ( noisefactor < 100 ) volume = (volume * noisefactor) / 100;
PlayJA2Sample( Weapon[ pObj->usItem ].sSound, RATE_11025, SoundVolume( volume, gridno ), 1, SoundDir( gridno ) );
}
}
///////////////////////// SOUND ////////////////////////////
// deduct ammo
(*pObj)[0]->data.gun.ubGunShotsLeft = max(0, (*pObj)[0]->data.gun.ubGunShotsLeft - 1);
//gTacticalStatus.ubAttackBusyCount++;
///////////////////////// SOUND ////////////////////////////
UINT8 ubVolume = Weapon[ pObj->usItem ].ubAttackVolume;
// Snap: get cumulative noise reduction from the weapon and its attachments
UINT16 noisefactor = GetPercentNoiseVolume( pObj );
if ( ubVolume * noisefactor > 25000 )
{ // Snap: hack this to prevent overflow (damn miserly programmers!)
ubVolume = 250;
}
else
{
ubVolume = __max( 1, ( ubVolume * GetPercentNoiseVolume( pObj ) ) / 100 );
}
MakeNoise( NOBODY, gridno, 0, pThrower->bOverTerrainType, ubVolume, NOISE_GUNFIRE );
///////////////////////// SOUND ////////////////////////////
///////////////////////// OVERHEATING AND STATUS REDUCTION ////////////////////////////
INT16 iOverheatReliabilityMalus = 0;
// Flugente: Increase Weapon Temperature
if ( gGameOptions.fWeaponOverheating )
{
FLOAT overheatjampercentage = GetGunOverheatDamagePercentage( pObj ); // ... how much above the gun's usOverheatingDamageThreshold are we? ...
if ( overheatjampercentage > 1.0 )
iOverheatReliabilityMalus = (INT16)floor(overheatjampercentage*overheatjampercentage);
GunIncreaseHeat( pObj );
}
// Flugente : Added a malus to reliability for overheated guns
// HEADROCK HAM 5: Variable NCTH base change
UINT32 uiDepreciateTest = 0;
if ( UsingNewCTHSystem() == true)
{
UINT16 usBaseChance = gGameCTHConstants.BASIC_RELIABILITY_ODDS;
FLOAT dReliabilityRatio = 3.0f * ((FLOAT)usBaseChance / (FLOAT)BASIC_DEPRECIATE_CHANCE); // Compare original odds to new odds.
uiDepreciateTest = usBaseChance + (INT16)( dReliabilityRatio * GetReliability( pObj ) - iOverheatReliabilityMalus);
uiDepreciateTest = max(0, uiDepreciateTest);
}
else
{
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 * GetReliability( pObj ) - iOverheatReliabilityMalus, 0);
}
if ( !PreRandom( uiDepreciateTest ) && ( (*pObj)[0]->data.objectStatus > 1) )
{
(*pObj)[0]->data.objectStatus--;
}
///////////////////////// OVERHEATING AND STATUS REDUCTION ////////////////////////////
///////////////////////// JAMMING ////////////////////////////
// Algorithm for jamming
int maxJamChance = 50; // Externalize this?
int reliability = GetReliability( pObj );
int condition = (*pObj)[0]->data.gun.bGunStatus;
int invertedBaseJamChance = condition + (reliability * 2) - gGameExternalOptions.ubWeaponReliabilityReductionPerRainIntensity * 1;
// Flugente FTW 1: If overheating is allowed, a gun will be prone to more overheating if its temperature is high
if ( gGameOptions.fWeaponOverheating )
{
FLOAT overheatjampercentage = GetGunOverheatJamPercentage( pObj ); // how much above the gun's usOverheatingJamThreshold are we? ...
int overheatjamfactor = (int)(100* overheatjampercentage); // We need an integer value and rough percentages
overheatjamfactor = max(0, overheatjamfactor - 100); // If we haven't reached the OverheatJamThreshold, no increased chance of jamming because of overheating
invertedBaseJamChance -= overheatjamfactor; // lower invertedBaseJamChance (thereby increasing jamChance later on)
}
if (invertedBaseJamChance < 0)
invertedBaseJamChance = 0;
else if (invertedBaseJamChance > 100)
invertedBaseJamChance = 100;
int jamChance = 100 - (int)sqrt((double)invertedBaseJamChance * (75.0 + (double)invertedBaseJamChance / 2.0));
if (jamChance < 0)
jamChance = 0;
else if (jamChance > maxJamChance - reliability)
jamChance = maxJamChance - reliability;
if ((INT32) PreRandom( 100 ) < jamChance )
{
// jam! negate the gun ammo status.
(*pObj)[0]->data.gun.bGunAmmoStatus *= -1;
}
///////////////////////// JAMMING ////////////////////////////
//<SB> manual recharge
if (Weapon[Item[pObj->usItem].ubClassIndex].APsToReloadManually > 0)
(*pObj)[0]->data.gun.ubGunState &= ~GS_CARTRIDGE_IN_CHAMBER;
//<SB>
return( TRUE );
}
+1 -4
View File
@@ -2232,13 +2232,10 @@ void CreateZombiefromCorpse( ROTTING_CORPSE * pCorpse, UINT16 usAnimState )
MercCreateStruct.fVisible = TRUE;
// do not generate a new palette, thereby using the old palette of the corpse
MercCreateStruct.fNoGenNewPalette = TRUE;
INT8 iNewIndex;
if ( TacticalCreateSoldier( &MercCreateStruct, (UINT8 *)&iNewIndex ) )
{
/* certain values have to be set afterwards - the alternative to edit each and every function that gets called from TacticalCreateSoldier() subsequently and
/* certain values have to be set afterwards - the alternative would be to edit each and every function that gets called from TacticalCreateSoldier() subsequently and
* make an exception for zombies every time...
*/
SOLDIERTYPE* pNewSoldier = MercPtrs[ (UINT8)iNewIndex ];
+13
View File
@@ -14374,10 +14374,23 @@ void SOLDIERTYPE::EVENT_SoldierBeginAttachCan( INT32 sGridNo, UINT8 ubDirection
}
extern UINT8 NumEnemiesInAnySector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ );
void SOLDIERTYPE::EVENT_SoldierBuildStructure( INT32 sGridNo, UINT8 ubDirection )
{
BOOLEAN fSuccess = FALSE;
// if specified by the ini, building/disassembling stuff is disabled while enemies are around
if ( !gGameExternalOptions.fFortificationAllowInHostileSector )
{
if( gWorldSectorX != -1 && gWorldSectorY != -1 && gWorldSectorX != 0 && gWorldSectorY != 0 &&
NumEnemiesInAnySector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) > 0 )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Cannot build while enemies are in this sector" );
return;
}
}
// do checks here...
OBJECTTYPE* pObj = &(this->inv[HANDPOS]);
+5 -4
View File
@@ -341,7 +341,6 @@ SOLDIERCREATE_STRUCT::SOLDIERCREATE_STRUCT() {
SOLDIERCREATE_STRUCT::SOLDIERCREATE_STRUCT(const SOLDIERCREATE_STRUCT& src) {
memcpy(this, &src, SIZEOF_SOLDIERCREATE_STRUCT_POD);
this->Inv = src.Inv;
this->fNoGenNewPalette = src.fNoGenNewPalette;
}
// Assignment operator
@@ -350,7 +349,6 @@ SOLDIERCREATE_STRUCT& SOLDIERCREATE_STRUCT::operator=(const SOLDIERCREATE_STRUCT
if (this != &src) {
memcpy(this, &src, SIZEOF_SOLDIERCREATE_STRUCT_POD);
this->Inv = src.Inv;
this->fNoGenNewPalette = src.fNoGenNewPalette;
}
return *this;
}
@@ -1360,6 +1358,10 @@ void GeneratePaletteForSoldier( SOLDIERTYPE *pSoldier, UINT8 ubSoldierClass )
BOOLEAN fMercClothingScheme;
hair = -1;
// Flugente: if all palettes are already set, no need to rebuild them. This allows zombies to use a corpses palettes
if( pSoldier->PantsPal[0] && pSoldier->VestPal[0] && pSoldier->SkinPal[0] && pSoldier->HeadPal[0] )
return;
//choose random skin tone which will limit the choice of hair colors.
skin = (INT8)Random( NUMSKINS );
switch( skin )
@@ -1739,8 +1741,7 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT
}
//Generate colors for soldier based on the body type.
if ( !pCreateStruct->fNoGenNewPalette )
GeneratePaletteForSoldier( pSoldier, pCreateStruct->ubSoldierClass );
GeneratePaletteForSoldier( pSoldier, pCreateStruct->ubSoldierClass );
// Copy item info over
pSoldier->inv = pCreateStruct->Inv;
-3
View File
@@ -305,9 +305,6 @@ public:
INT8 bUseGivenVehicleID;
BOOLEAN fHasKeys;
// Flugente: do not generate new palette for soldier (for soldiers that are created from existing soldiers/corpses, like doppelgangers and zombies)
BOOLEAN fNoGenNewPalette;
//
// New and OO stuff goes after here. Above this point any changes will goof up reading from files.
//
+1 -1
View File
@@ -271,7 +271,7 @@ void HandleTacticalEndTurn( )
HandleRPCDescription( );
#endif
// Flugente FTW 1: Cool down all items not in a soldier's inventory
// Flugente: Cool down all items not in a soldier's inventory
CoolDownWorldItems( FALSE );
// Flugente: raise zombies if in gamescreen and option set
if ( guiCurrentScreen == GAME_SCREEN )
+8
View File
@@ -459,6 +459,14 @@ void EndTurnEvents( void )
DecaySmokeEffects( GetWorldTotalSeconds( ) );
DecayLightEffects( GetWorldTotalSeconds( ) );
// Flugente: Cool down all items not in a soldier's inventory
CoolDownWorldItems( FALSE );
// Flugente: raise zombies if in gamescreen and option set
if ( guiCurrentScreen == GAME_SCREEN )
{
RaiseZombies();
}
// decay AI warning values from corpses
DecayRottingCorpseAIWarnings();