mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
[Fix] A bunch of fixes for artillery strike
* Avoid using hard-coded Signal and HE mortar shell indices. This caused art.strikes malfunctioning in item mods. * Trim max nubers of waves to duration of signal smoke. Otherwise art.strike turns into unnatural stupidity. * If enemy AI tried to get art.strike but lacked of resources, player will not a warning anymore.
This commit is contained in:
@@ -8,3 +8,6 @@
|
||||
/out/
|
||||
/CMakeSettings.json
|
||||
/CMakeUserPresets.json
|
||||
|
||||
# My shelves
|
||||
.shelve/
|
||||
|
||||
+1
-1
@@ -2845,7 +2845,7 @@ void LoadSkillTraitsExternalSettings()
|
||||
// Flugente: RADIO OPERATOR
|
||||
gSkillTraitValues.fROAllowArtillery = iniReader.ReadBoolean("Radio Operator","RADIO_OPERATOR_ARTILLERY", TRUE);
|
||||
gSkillTraitValues.fROArtilleryDistributedOverTurns = iniReader.ReadBoolean("Radio Operator","RADIO_OPERATOR_ARTILLERY_DISTRIBUTED_OVER_TURNS", FALSE);
|
||||
gSkillTraitValues.bVOArtillerySectorFrequency = iniReader.ReadInteger("Radio Operator","RADIO_OPERATOR_ARTILLERY_SECTOR_FREQUENCY", 120, 20, 1440);
|
||||
gSkillTraitValues.bVOArtillerySectorFrequency = iniReader.ReadInteger("Radio Operator","RADIO_OPERATOR_ARTILLERY_SECTOR_FREQUENCY", 120, 5, 1440);
|
||||
gSkillTraitValues.usVOMortarCountDivisor = iniReader.ReadInteger("Radio Operator","RADIO_OPERATOR_MORTAR_COUNT_DIVISOR", 6, 5, 20);
|
||||
gSkillTraitValues.usVOMortarShellDivisor = iniReader.ReadInteger("Radio Operator","RADIO_OPERATOR_MORTAR_SHELL_DIVISOR", 30, 2, 100);
|
||||
gSkillTraitValues.usVOMortarPointsAdmin = iniReader.ReadInteger("Radio Operator","RADIO_OPERATOR_MORTAR_POINTS_ADMIN", 10, 0, 100);
|
||||
|
||||
@@ -4121,7 +4121,7 @@ void TakeMilitiaEquipmentfromSector( INT16 sMapX, INT16 sMapY, INT8 sMapZ, SOLDI
|
||||
|
||||
if ( uiTotalNumberOfRealItems == 0 )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Militia found no items to equip, uses harsh langugage instead!" );
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Militia found no items to equip, uses harsh language instead!" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -16015,3 +16015,21 @@ bool HasScopeMagFactorForGun( UINT16 ausItemGun, FLOAT aFactor )
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT16 GetLaunchableOfExplosionType(UINT16 launcher, UINT8 explosionType)
|
||||
{
|
||||
for (int i = 0; i < MAXITEMS; i++)
|
||||
{
|
||||
UINT16 launchable = Launchable[i][0];
|
||||
|
||||
if (launchable == 0) // if reached end of Launchable list, then stop
|
||||
break;
|
||||
|
||||
if (Launchable[i][1] == launcher)
|
||||
{
|
||||
if (Explosive[Item[launchable].ubClassIndex].ubType == explosionType)
|
||||
return launchable;
|
||||
}
|
||||
}
|
||||
return NOTHING;
|
||||
}
|
||||
|
||||
@@ -576,5 +576,6 @@ FLOAT GetAttackAPTraitMultiplier( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, UINT8
|
||||
|
||||
// sevenfm: check if this type of grenade can use delayed mode
|
||||
BOOLEAN CanDelayGrenadeExplosion( UINT16 usItem );
|
||||
UINT16 GetLaunchableOfExplosionType(UINT16 launcher, UINT8 explosionType);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18643,14 +18643,42 @@ BOOLEAN SOLDIERTYPE::OrderArtilleryStrike( UINT32 usSectorNr, INT32 sTargetGridN
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Locate item indices for Signal and HE shells defined by the active MOD. Evade usage of hard-code values.
|
||||
static UINT16 usSignalShellIndex = NOTHING;
|
||||
static UINT16 usHeShellIndex = NOTHING;
|
||||
if (usSignalShellIndex == NOTHING || usHeShellIndex == NOTHING)
|
||||
{
|
||||
UINT16 findSignalShellIndex = 1700; // try default Signal Shell item in 1.13
|
||||
UINT16 findHeShellIndex = 140; // try default HE Shell item in 1.13
|
||||
if (HasItemFlag(findSignalShellIndex, SIGNAL_SHELL) == FALSE && GetFirstItemWithFlag(&findSignalShellIndex, SIGNAL_SHELL) == FALSE)
|
||||
{
|
||||
ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_NO_SIGNAL_SHELL]);
|
||||
return FALSE;
|
||||
}
|
||||
UINT16 mortarIndex = GetLauncherFromLaunchable(findSignalShellIndex);
|
||||
if (mortarIndex != GetLauncherFromLaunchable(findHeShellIndex))
|
||||
{
|
||||
findHeShellIndex = GetLaunchableOfExplosionType(mortarIndex, EXPLOSV_NORMAL);
|
||||
}
|
||||
if (findHeShellIndex == NOTHING)
|
||||
{
|
||||
ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_NO_DEFAULT_SHELL]);
|
||||
return FALSE;
|
||||
}
|
||||
// at this point both shells were found and are OK, so set it to static variables and never touch anymore:
|
||||
usSignalShellIndex = findSignalShellIndex;
|
||||
usHeShellIndex = findHeShellIndex;
|
||||
}
|
||||
|
||||
// if a strike is ordered from the ENEMY_TEAM or MILITIA_TEAM, the number of mortars depends on the number of enemies/militia in that sector
|
||||
// number of waves depends on the number and quality of enemies/soldiers
|
||||
// only HE shells will be fired this way
|
||||
if ( bTeam == ENEMY_TEAM || bTeam == MILITIA_TEAM )
|
||||
{
|
||||
INT16 nummortars = 0; // number of mortars determines size of wave (1 - 4)
|
||||
INT16 numwaves = 0; // number of waves
|
||||
INT16 numshells = 0; // number of shells
|
||||
INT16 nummortars = 0; // number of mortars determines size of wave (1 - 4)
|
||||
INT16 numwaves = 0; // number of waves
|
||||
INT16 numshells = 0; // number of shells
|
||||
INT16 numwavesMax = (INT16) Explosive[Item[usSignalShellIndex].ubClassIndex].ubDuration;
|
||||
|
||||
SECTORINFO *pSector = &SectorInfo[SECTOR( sSectorX, sSectorY )];
|
||||
|
||||
@@ -18682,35 +18710,36 @@ BOOLEAN SOLDIERTYPE::OrderArtilleryStrike( UINT32 usSectorNr, INT32 sTargetGridN
|
||||
numshells = gSkillTraitValues.usVOMortarPointsAdmin * militia_green + gSkillTraitValues.usVOMortarPointsTroop * militia_troop + gSkillTraitValues.usVOMortarPointsElite * militia_elite;
|
||||
}
|
||||
|
||||
if ( gSkillTraitValues.usVOMortarShellDivisor * nummortars < 1 )
|
||||
// turn number of mortar points into number of shells; in case of "militia use sector ammo" option, numshells
|
||||
// represents max potential shells militia can shot for this artillery strike.
|
||||
numshells = numshells / gSkillTraitValues.usVOMortarShellDivisor;
|
||||
|
||||
if (numshells <= 0)
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_NOT_ENOUGH_MORTAR_SHELLS] );
|
||||
if (bTeam == MILITIA_TEAM) // player does not care if enemy team has not enough points to strike
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_NOT_ENOUGH_MORTAR_SHELLS] );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
numwaves = numshells / (gSkillTraitValues.usVOMortarShellDivisor * nummortars);
|
||||
|
||||
if ( !numwaves )
|
||||
if (nummortars <= 0)
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_NOT_ENOUGH_MORTAR_SHELLS] );
|
||||
if (bTeam == MILITIA_TEAM) // player does not care if enemy team has not enough men to strike
|
||||
ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_NO_MORTARS]);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
numwaves = max(1, numshells / nummortars);
|
||||
if (gSkillTraitValues.fROArtilleryDistributedOverTurns) // if delay between waves is enabled, we shouldn't overextend, so trim to
|
||||
numwaves = min(numwaves, numwavesMax); // signal duration; it doesn't matter if delay is disabled.
|
||||
|
||||
// send a signal shell at first. This marks the area that the shells will come in
|
||||
static UINT16 usSignalShellIndex = 1700;
|
||||
if ( HasItemFlag( usSignalShellIndex, SIGNAL_SHELL ) || GetFirstItemWithFlag( &usSignalShellIndex, SIGNAL_SHELL ) )
|
||||
ArtilleryStrike( usSignalShellIndex, this->ubID + 2, sStartingGridNo, sTargetGridNo );
|
||||
else
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_NO_SIGNAL_SHELL] );
|
||||
return FALSE;
|
||||
}
|
||||
ArtilleryStrike(usSignalShellIndex, this->ubID + 2, sStartingGridNo, sTargetGridNo);
|
||||
|
||||
// we just 'plant' the mortar shells as bombs. We time them so that they will be fired at the beginning of the next turn
|
||||
// for every 'wave' of shells, we just plant one and then clone them when firing
|
||||
// create mortar shell item
|
||||
OBJECTTYPE shellobj;
|
||||
CreateItem( 140, 100, &shellobj ); // 140 is mortar HE shell
|
||||
CreateItem(usHeShellIndex, 100, &shellobj );
|
||||
|
||||
shellobj.fFlags |= OBJECT_ARMED_BOMB;
|
||||
shellobj[0]->data.misc.bDetonatorType = BOMB_TIMED;
|
||||
@@ -18772,17 +18801,15 @@ BOOLEAN SOLDIERTYPE::OrderArtilleryStrike( UINT32 usSectorNr, INT32 sTargetGridN
|
||||
|
||||
// as of 2013-09-25, I say it is no longer necessary to fire a signal shell first. The player can fire a signal shell (by mortar or hand) manually to mark one or more targets if he wants
|
||||
// if he does not do so, active vox operators will be targetted. Who knows, the vox operator might be doing a heroic last stand for all we know...
|
||||
UINT8 radiooperatorID = 0;
|
||||
//BOOLEAN signalshellfired = FALSE;
|
||||
const UINT8 maxFiringMortarsAmount = 5;
|
||||
UINT8 radiooperatorID = 0;
|
||||
UINT8 mortaritemcnt = 0;
|
||||
UINT16 mortararray[5];
|
||||
for ( UINT8 i = 0; i < 5; ++i )
|
||||
mortararray[i] = 0;
|
||||
UINT16 mortararray[maxFiringMortarsAmount] = { 0 };
|
||||
|
||||
SOLDIERTYPE* pSoldier = NULL;
|
||||
INT32 cnt = gTacticalStatus.Team[bTeam].bFirstID;
|
||||
INT32 lastid = gTacticalStatus.Team[bTeam].bLastID;
|
||||
for ( pSoldier = MercPtrs[cnt]; cnt < lastid; ++cnt, ++pSoldier )
|
||||
for ( pSoldier = MercPtrs[cnt]; (cnt < lastid) && (mortaritemcnt < maxFiringMortarsAmount); ++cnt, ++pSoldier )
|
||||
{
|
||||
// check if soldier exists in this sector
|
||||
if ( !pSoldier || !pSoldier->bActive || pSoldier->sSectorX != sSectorX || pSoldier->sSectorY != sSectorY || pSoldier->bSectorZ != bSectorZ || pSoldier->bAssignment > ON_DUTY )
|
||||
@@ -18791,70 +18818,25 @@ BOOLEAN SOLDIERTYPE::OrderArtilleryStrike( UINT32 usSectorNr, INT32 sTargetGridN
|
||||
if ( pSoldier->CanUseRadio( ) )
|
||||
radiooperatorID = cnt;
|
||||
|
||||
/*if ( !signalshellfired )
|
||||
{
|
||||
UINT8 bSlot = 0;
|
||||
if ( pSoldier->GetSlotOfSignalShellIfMortar(&bSlot) )
|
||||
{
|
||||
OBJECTTYPE* pSlotObj = &(pSoldier->inv[bSlot]);
|
||||
INT8 invsize = (INT8)pSoldier->inv.size( ); // remember inventorysize, so we don't call size() repeatedly
|
||||
|
||||
if ( Item[pSlotObj->usItem].mortar )
|
||||
{
|
||||
pSlotObj = FindAttachmentByClass( &(pSoldier->inv[bSlot]), IC_BOMB );
|
||||
|
||||
if ( pSlotObj )
|
||||
{
|
||||
ArtilleryStrike(pSlotObj->usItem, sStartingGridNo, sTargetGridNo);
|
||||
|
||||
DeductAmmo( pSoldier, bSlot );
|
||||
|
||||
signalshellfired = TRUE;
|
||||
}
|
||||
}
|
||||
else if ( HasItemFlag(pSoldier->inv[bSlot].usItem, SIGNAL_SHELL) )
|
||||
{
|
||||
ArtilleryStrike(pSlotObj->usItem, sStartingGridNo, sTargetGridNo);
|
||||
|
||||
pSlotObj->ubNumberOfObjects--;
|
||||
|
||||
if ( !pSlotObj->exists() )
|
||||
{
|
||||
// Delete object
|
||||
DeleteObj( pSlotObj );
|
||||
}
|
||||
|
||||
signalshellfired = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// somethings wrong... we were promised either a signal shell or a mortar with one loaded, but there is none... betrayal!
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"No signal shell found even though there should be one, cannot commence barrage!");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
INT8 invsize = (INT8)pSoldier->inv.size( ); // remember inventorysize, so we don't call size() repeatedly
|
||||
|
||||
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop )
|
||||
for ( INT8 bLoop = 0; (bLoop < invsize) && (mortaritemcnt < maxFiringMortarsAmount); ++bLoop )
|
||||
{
|
||||
if ( pSoldier->inv[bLoop].exists( ) == true && Item[pSoldier->inv[bLoop].usItem].mortar )
|
||||
{
|
||||
// if not already in list, remember this mortar
|
||||
if ( mortararray[0] != pSoldier->inv[bLoop].usItem &&
|
||||
mortararray[1] != pSoldier->inv[bLoop].usItem &&
|
||||
mortararray[2] != pSoldier->inv[bLoop].usItem &&
|
||||
mortararray[3] != pSoldier->inv[bLoop].usItem &&
|
||||
mortararray[4] != pSoldier->inv[bLoop].usItem )
|
||||
mortararray[mortaritemcnt++] = pSoldier->inv[bLoop].usItem;
|
||||
bool alreadyInList = false;
|
||||
for (INT8 i = 0; i < mortaritemcnt; i++)
|
||||
if (mortararray[i] == pSoldier->inv[bLoop].usItem)
|
||||
{
|
||||
alreadyInList = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (alreadyInList == false)
|
||||
mortararray[mortaritemcnt++] = pSoldier->inv[bLoop].usItem;
|
||||
}
|
||||
|
||||
if ( mortaritemcnt >= 5 )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( mortaritemcnt >= 5 )
|
||||
break;
|
||||
}
|
||||
|
||||
// safety check, this shouldn't be happening
|
||||
@@ -18864,16 +18846,6 @@ BOOLEAN SOLDIERTYPE::OrderArtilleryStrike( UINT32 usSectorNr, INT32 sTargetGridN
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// no signal shell -> no barrage
|
||||
/*if ( !signalshellfired )
|
||||
{
|
||||
if ( radiooperatorID )
|
||||
DelayedTacticalCharacterDialogue( MercPtrs[ radiooperatorID ], QUOTE_OUT_OF_AMMO );
|
||||
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"No signal shell object found, cannot commence barrage!");
|
||||
return FALSE;
|
||||
}*/
|
||||
|
||||
// depending on wether the mortars have ammunition, a radio operator will give a different dialogue
|
||||
BOOLEAN shellsfired = FALSE;
|
||||
|
||||
@@ -18901,7 +18873,7 @@ BOOLEAN SOLDIERTYPE::OrderArtilleryStrike( UINT32 usSectorNr, INT32 sTargetGridN
|
||||
|
||||
// as of 2013-09-25, also fire these, as they are no longer necessary for a barrage
|
||||
// only fire if not signal shell, we already fired one, no need to do so again
|
||||
if ( pAttObj )//&& !HasItemFlag(pAttObj->usItem, SIGNAL_SHELL) )
|
||||
if ( pAttObj && HasItemFlag(pAttObj->usItem, SIGNAL_SHELL) == FALSE )
|
||||
{
|
||||
// if option is set, delay each wave by one turn
|
||||
if ( gSkillTraitValues.fROArtilleryDistributedOverTurns )
|
||||
|
||||
@@ -2549,6 +2549,7 @@ enum
|
||||
MSG113_RADIO_ACTION_FAILED,
|
||||
MSG113_NOT_ENOUGH_MORTAR_SHELLS,
|
||||
MSG113_NO_SIGNAL_SHELL,
|
||||
MSG113_NO_DEFAULT_SHELL,
|
||||
MSG113_NO_MORTARS,
|
||||
MSG113_ALREADY_JAMMING,
|
||||
MSG113_ALREADY_LISTENING,
|
||||
|
||||
@@ -7667,6 +7667,7 @@ STR16 New113Message[] =
|
||||
L"无线电操作失败!",
|
||||
L"迫击炮弹不足,无法在分区发动密集轰炸!",
|
||||
L"Items.xml里没有定义信号弹物品!",
|
||||
L"No High-Explosive shell item found in Items.xml!",
|
||||
L"未发现迫击炮,无法执行密集轰炸!",
|
||||
L"干扰信号成功,不需要重复操作!",
|
||||
L"正在监听周围声音,无需重复操作!",
|
||||
|
||||
@@ -7673,6 +7673,7 @@ STR16 New113Message[] =
|
||||
L"Radio action failed!",
|
||||
L"Not enough mortar shells in sector to start a barrage!",
|
||||
L"No signal shell item found in Items.xml!",
|
||||
L"No High-Explosive shell item found in Items.xml!",
|
||||
L"No mortars found, cannot commence barrage!",
|
||||
L"Already jamming signal, no need to do so again!",
|
||||
L"Already listening for nearby sounds, no need to do so again!",
|
||||
|
||||
@@ -7667,6 +7667,7 @@ STR16 New113Message[] =
|
||||
L"Radio action failed!",
|
||||
L"Not enough mortar shells in sector to start a barrage!",
|
||||
L"No signal shell item found in Items.xml!",
|
||||
L"No High-Explosive shell item found in Items.xml!",
|
||||
L"No mortars found, cannot commence barrage!",
|
||||
L"Already jamming signal, no need to do so again!",
|
||||
L"Already listening for nearby sounds, no need to do so again!",
|
||||
|
||||
@@ -7670,6 +7670,7 @@ STR16 New113Message[] =
|
||||
L"L'action radio a échoué !",
|
||||
L"Pas assez d'obus de mortier dans le secteur pour un tir de barrage !",
|
||||
L"Aucun obus éclairant trouvé dans Items.xml !",
|
||||
L"No High-Explosive shell item found in Items.xml!",
|
||||
L"Aucun mortier trouvé, tir de barrage impossible !",
|
||||
L"Brouillage radio déjà en cours, inutile d'en lancer un autre !",
|
||||
L"Écoute des sons alentour déjà en cours, inutile d'en lancer une autre !",
|
||||
|
||||
@@ -7524,6 +7524,7 @@ STR16 New113Message[] =
|
||||
L"Radio action failed!",
|
||||
L"Not enough mortar shells in sector to start a barrage!",
|
||||
L"No signal shell item found in Items.xml!",
|
||||
L"No High-Explosive shell item found in Items.xml!",
|
||||
L"No mortars found, cannot commence barrage!",
|
||||
L"Already jamming signal, no need to do so again!",
|
||||
L"Already listening for nearby sounds, no need to do so again!",
|
||||
|
||||
@@ -7664,6 +7664,7 @@ STR16 New113Message[] =
|
||||
L"Radio action failed!",
|
||||
L"Not enough mortar shells in sector to start a barrage!",
|
||||
L"No signal shell item found in Items.xml!",
|
||||
L"No High-Explosive shell item found in Items.xml!",
|
||||
L"No mortars found, cannot commence barrage!",
|
||||
L"Already jamming signal, no need to do so again!",
|
||||
L"Already listening for nearby sounds, no need to do so again!",
|
||||
|
||||
@@ -7673,6 +7673,7 @@ STR16 New113Message[] =
|
||||
L"Radio action failed!",
|
||||
L"Not enough mortar shells in sector to start a barrage!",
|
||||
L"No signal shell item found in Items.xml!",
|
||||
L"No High-Explosive shell item found in Items.xml!",
|
||||
L"No mortars found, cannot commence barrage!",
|
||||
L"Already jamming signal, no need to do so again!",
|
||||
L"Already listening for nearby sounds, no need to do so again!",
|
||||
|
||||
@@ -7662,6 +7662,7 @@ STR16 New113Message[] =
|
||||
L"Не удалось использовать радиостанцию!",
|
||||
L"Недостаточно миномётных снарядов в секторе для постановки огня!",
|
||||
L"Не обнаружены сигнальные мины в Items.xml!",
|
||||
L"Не обнаружены осколочно-фугасные мины в Items.xml!",
|
||||
L"Нет миномётов, невозможно организовать артналет!",
|
||||
L"Режим радиопомех уже включен, нет необходимости делать это снова!",
|
||||
L"Режим прослушивания звуков уже включен, нет необходимости делать это снова!",
|
||||
|
||||
Reference in New Issue
Block a user