Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@
/out/
/CMakeSettings.json
/CMakeUserPresets.json

# My shelves
.shelve/
2 changes: 1 addition & 1 deletion GameSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion Tactical/Inventory Choosing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
18 changes: 18 additions & 0 deletions Tactical/Items.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
1 change: 1 addition & 0 deletions Tactical/Items.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
156 changes: 64 additions & 92 deletions Tactical/Soldier Control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 )];

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 )
Expand All @@ -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]);

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 );
}
INT8 invsize = (INT8)pSoldier->inv.size( ); // remember inventorysize, so we don't call size() repeatedly

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 ( mortaritemcnt >= 5 )
break;
if (alreadyInList == false)
mortararray[mortaritemcnt++] = pSoldier->inv[bLoop].usItem;
}
}

if ( mortaritemcnt >= 5 )
break;
}

// safety check, this shouldn't be happening
Expand All @@ -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;

Expand Down Expand Up @@ -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 )
Expand Down
1 change: 1 addition & 0 deletions Utils/Text.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions Utils/_ChineseText.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7667,6 +7667,7 @@ STR16 New113Message[] =
L"无线电操作失败!",
L"迫击炮弹不足,无法在分区发动密集轰炸!",
L"Items.xml里没有定义信号弹物品!",
L"No High-Explosive shell item found in Items.xml!",
L"未发现迫击炮,无法执行密集轰炸!",
L"干扰信号成功,不需要重复操作!",
L"正在监听周围声音,无需重复操作!",
Expand Down
1 change: 1 addition & 0 deletions Utils/_DutchText.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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!",
Expand Down
1 change: 1 addition & 0 deletions Utils/_EnglishText.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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!",
Expand Down
1 change: 1 addition & 0 deletions Utils/_FrenchText.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 !",
Expand Down
1 change: 1 addition & 0 deletions Utils/_GermanText.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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!",
Expand Down
1 change: 1 addition & 0 deletions Utils/_ItalianText.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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!",
Expand Down
1 change: 1 addition & 0 deletions Utils/_PolishText.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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!",
Expand Down
1 change: 1 addition & 0 deletions Utils/_RussianText.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7662,6 +7662,7 @@ STR16 New113Message[] =
L"Не удалось использовать радиостанцию!",
L"Недостаточно миномётных снарядов в секторе для постановки огня!",
L"Не обнаружены сигнальные мины в Items.xml!",
L"Не обнаружены осколочно-фугасные мины в Items.xml!",
L"Нет миномётов, невозможно организовать артналет!",
L"Режим радиопомех уже включен, нет необходимости делать это снова!",
L"Режим прослушивания звуков уже включен, нет необходимости делать это снова!",
Expand Down