New feature: radio operator trait allows calling in artillery, requesting reinforcements, scanning for enemies and a few other skills.

Also includes mechansim for easy implementation of new skills.

For more info see http://www.bears-pit.com/board/ubbthreads.php/topics/327348.html#Post327348

Requires GameDir >= r1848.

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6547 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2013-10-30 23:05:37 +00:00
parent bef4e7b52b
commit f17829fac9
80 changed files with 4722 additions and 243 deletions
+288 -20
View File
@@ -67,6 +67,15 @@ enum MINES_VALUES
MAX_MINES
};
// Flugente: trait display
enum TRAIT_VALUES
{
TRAIT_ALL = MAX_MINES + 1,
TRAIT_1,
TRAIT_2,
MAX_TRAIT
};
struct CoverCell
{
@@ -75,8 +84,9 @@ struct CoverCell
BOOLEAN fInverseColor;
INT8 bMines;
INT8 bTrait;
CoverCell() : sGridNo(NOWHERE), bCover(INVALID_COVER), fInverseColor(FALSE), bMines(MINES_ALL) {}
CoverCell() : sGridNo(NOWHERE), bCover(INVALID_COVER), fInverseColor(FALSE), bMines(MINES_ALL), bTrait(TRAIT_ALL) {}
};
@@ -111,6 +121,13 @@ enum MINES_DRAW_MODE {
MINES_DRAW_MAX
};
// Flugente: trait draw mode
enum TRAIT_DRAW_MODE {
TRAIT_DRAW_OFF,
TRAIT_DRAW_RANGE,
TRAIT_DRAW_MAX
};
//****** Local Variables *********************************************
@@ -124,6 +141,8 @@ COVER_DRAW_MODE gubDrawMode = COVER_DRAW_OFF;
MINES_DRAW_MODE gubDrawModeMine = MINES_DRAW_OFF; // Flugente: mines display
TRAIT_DRAW_MODE gubDrawModeTrait = TRAIT_DRAW_OFF; // Flugente: mines display
//******* Local Function Prototypes ***********************************
@@ -138,7 +157,7 @@ void AddCoverObjectsToViewArea();
void RemoveCoverObjectsFromViewArea();
void RemoveMinesObjectsFromViewArea(); // added by Flugente, has to be declared here
void RemoveTraitObjectsFromViewArea();
void CalculateCover();
void CalculateCoverForSoldier( SOLDIERTYPE* pForSoldier, const INT32& sTargetGridNo, const BOOLEAN& fRoof, INT8& bCover );
@@ -746,11 +765,6 @@ void ToggleHostileTrapsView()
void ToggleTrapNetworkView()
{
SwitchMinesDrawModeForNetworks();
/*if (gubDrawModeMine == MINES_DRAW_PLAYERTEAM_NETWORKS) {
SwitchMineViewOff();
} else {
SwitchToTrapNetworkView();
}*/
}
void SwitchMinesDrawModeForNetworks()
@@ -797,19 +811,6 @@ void SwitchMinesDrawModeForNetworks()
DisplayMines(TRUE);
break;
}
/*switch(gubDrawModeMine)
{
case MINES_DRAW_OFF:
SwitchToTrapNetworkView();
break;
case MINES_DRAW_PLAYERTEAM_NETWORKS:
SwitchToHostileTrapsView();
break;
default:
SwitchMineViewOff();
break;
}*/
}
///END key binding functions
@@ -1254,3 +1255,270 @@ void DetermineMineDisplayInTile( INT32 sGridNo, INT8 bLevel, INT8& bMines, BOOLE
}
}
// ----------------------------- trait range display after this ----------------------------------------
// added by Flugente
//******* Local Function Prototypes ***********************************
TileDefines GetTileTraitIndex( const INT8& bTrait );
void AddTraitObjectsToViewArea();
void CalculateTraitRange();
BOOLEAN TraitTileHasAdjTile( const INT32& ubX, const INT32& ubY, const INT32& ubZ );
UINT32 usDisplayTrait = NO_SKILLTRAIT_NT;
INT32 sTraitgridNo = NOWHERE;
///BEGIN key binding functions
void ToggleTraitRangeView(BOOLEAN fOn)
{
if ( fOn )
{
gubDrawModeTrait = TRAIT_DRAW_RANGE;
gubDrawMode = COVER_DRAW_OFF;
gubDrawModeMine = MINES_DRAW_OFF;
}
else
{
gubDrawModeTrait = TRAIT_DRAW_OFF;
SetTraitToDisplay( NO_SKILLTRAIT_NT );
SetGridNoForTraitDisplay( NOWHERE );
}
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Display trait ranges");
DisplayTraitRange(TRUE);
}
void SetTraitToDisplay( UINT32 aTrait )
{
usDisplayTrait = aTrait;
}
void SetGridNoForTraitDisplay( INT32 sGridNo )
{
sTraitgridNo = sGridNo;
}
void DisplayTraitRange( const BOOLEAN& forceUpdate )
{
if ( gGameExternalOptions.ubCoverDisplayUpdateWait == -1 )
{
return;
}
if ( forceUpdate || ( !gfScrollPending && !gfScrollInertia && GetTickCount() > guiMinesNextUpdateTime ) )
{
CalculateTraitRange();
guiMinesNextUpdateTime = GetTickCount() + gGameExternalOptions.ubCoverDisplayUpdateWait;
}
}
void CalculateTraitRange()
{
INT32 ubX, ubY, ubZ;
SOLDIERTYPE* pSoldier;
RemoveTraitObjectsFromViewArea();
if ( gubDrawModeTrait == TRAIT_DRAW_OFF )
return;
if( gusSelectedSoldier == NOBODY || !GetSoldier( &pSoldier, gusSelectedSoldier ) )
return;
UINT16 range1 = 0;
UINT16 range2 = 0;
switch ( usDisplayTrait )
{
case RADIO_OPERATOR_NT:
{
// we 'mark' the map position with which we called the menu, so that the player sees where he is targetting
}
break;
default:
return;
}
//remove other displays
if( gubDrawModeMine != MINES_DRAW_OFF )
RemoveMinesObjectsFromViewArea();
if ( gubDrawMode != COVER_DRAW_OFF )
RemoveCoverObjectsFromViewArea();
const INT32& sSelectedSoldierGridNo = MercPtrs[ gusSelectedSoldier ]->sGridNo;
INT16 usTmp;
GetScreenXYWorldCell( gsVIEWPORT_START_X, gsVIEWPORT_START_Y, &gsMineMinCellX, &usTmp );
GetScreenXYWorldCell( gsVIEWPORT_END_X, gsVIEWPORT_END_Y, &gsMineMaxCellX, &usTmp );
GetScreenXYWorldCell( gsVIEWPORT_END_X, gsVIEWPORT_START_Y, &usTmp, &gsMineMinCellY );
GetScreenXYWorldCell( gsVIEWPORT_START_X, gsVIEWPORT_END_Y, &usTmp, &gsMineMaxCellY );
for ( ubX=gsMineMinCellX; ubX<=gsMineMaxCellX; ++ubX )
{
for ( ubY=gsMineMinCellY; ubY<=gsMineMaxCellY; ++ubY )
{
for ( ubZ=0; ubZ<COVER_Z_CELLS; ++ubZ )
{
INT32& sGridNo = gCoverViewArea[ ubX ][ ubY ][ ubZ ].sGridNo;
GetGridNoForViewPort( ubX, ubY, sGridNo );
if( !GridNoOnScreenAndAround( sGridNo, 2 ) )
{
continue;
}
if ( !NewOKDestination( pSoldier, sGridNo, false, (INT8) ubZ ) )
{
continue;
}
// do not show stuff on roofs if ground is shown
if ( ubZ == I_ROOF_LEVEL && !IsTheRoofVisible( sGridNo ) )
{
continue;
}
// do not show stuff on ground if roof is shown
if ( ubZ == I_GROUND_LEVEL && IsTheRoofVisible( sGridNo ) )
{
continue;
}
if ( range1 && PythSpacesAway(sSelectedSoldierGridNo, sGridNo) == range1 )
gCoverViewArea[ ubX ][ ubY ][ ubZ ].bTrait = TRAIT_1;
else if ( range2 && PythSpacesAway(sSelectedSoldierGridNo, sGridNo) == range2 )
gCoverViewArea[ ubX ][ ubY ][ ubZ ].bTrait = TRAIT_2;
// mark the gridno we are targetting
else if ( PythSpacesAway(sTraitgridNo, sGridNo) == 1 )
gCoverViewArea[ ubX ][ ubY ][ ubZ ].bTrait = TRAIT_1;
else
gCoverViewArea[ ubX ][ ubY ][ ubZ ].bTrait = MAX_TRAIT;
}
}
}
AddTraitObjectsToViewArea();
}
void AddTraitObjectsToViewArea()
{
if (gsMineMaxCellY == -1)
{
return;
}
INT32 ubX, ubY, ubZ;
BOOLEAN fChanged = FALSE;
for ( ubX=gsMineMinCellX; ubX<=gsMineMaxCellX; ++ubX )
{
for ( ubY=gsMineMinCellY; ubY<=gsMineMaxCellY; ++ubY )
{
for ( ubZ=0; ubZ<COVER_Z_CELLS; ++ubZ )
{
INT32& sGridNo = gCoverViewArea[ ubX ][ ubY ][ ubZ ].sGridNo;
INT8& bTrait = gCoverViewArea[ ubX ][ ubY ][ ubZ ].bTrait;
if ( bTrait != -1 && ( bTrait == TRAIT_1 || bTrait == TRAIT_2 ) )
{
TileDefines tile = GetTileTraitIndex( bTrait );
AddCoverObjectToWorld( sGridNo, tile, (BOOLEAN) ubZ );
fChanged = TRUE;
}
}
}
}
// Re-render the scene!
if ( fChanged )
{
SetRenderFlags( RENDER_FLAG_FULL );
}
}
TileDefines GetTileTraitIndex( const INT8& bTrait )
{
switch(bTrait)
{
case TRAIT_1:
return SPECIALTILE_COVER_5; // green
case TRAIT_2:
return SPECIALTILE_COVER_2; // orange
case TRAIT_ALL:
return SPECIALTILE_COVER_3; // yellow
case MAX_TRAIT:
default:
return SPECIALTILE_COVER_1; // red
}
}
BOOLEAN TraitTileHasAdjTile( const INT32& ubX, const INT32& ubY, const INT32& ubZ )
{
INT32 ubTX, ubTY;
for ( ubTX = ubX-1; ubTX <= ubX+1; ++ubTX )
{
if ( ubTX < 0 || ubTX > WORLD_COLS )
{
continue;
}
for ( ubTY = ubY-1; ubTY <= ubY+1; ++ubTY )
{
if ( ubTY < 0 || ubTY > WORLD_ROWS )
{
continue;
}
INT8& bTrait = gCoverViewArea[ ubTX ][ ubTY ][ ubZ ].bTrait;
if ( bTrait == TRAIT_1 || bTrait == TRAIT_2 )
{
return TRUE;
}
}
}
return FALSE;
}
void RemoveTraitObjectsFromViewArea()
{
if (gsMineMaxCellY == -1)
{
return;
}
INT32 ubX, ubY, ubZ;
BOOLEAN fChanged = FALSE;
for ( ubX=gsMineMinCellX; ubX<=gsMineMaxCellX; ++ubX )
{
for ( ubY=gsMineMinCellY; ubY<=gsMineMaxCellY; ++ubY )
{
for ( ubZ=0; ubZ<COVER_Z_CELLS; ++ubZ )
{
INT32& sGridNo = gCoverViewArea[ ubX ][ ubY ][ ubZ ].sGridNo;
INT8& bTrait = gCoverViewArea[ ubX ][ ubY ][ ubZ ].bTrait;
if ( bTrait != -1 || TraitTileHasAdjTile( ubX, ubY, ubZ ))
{
TileDefines tile = GetTileTraitIndex( bTrait );
RemoveCoverObjectFromWorld( sGridNo, tile, (BOOLEAN) ubZ );
bTrait = -1;
fChanged = TRUE;
}
}
}
}
// Re-render the scene!
if ( fChanged )
{
SetRenderFlags( RENDER_FLAG_FULL );
}
}
+7
View File
@@ -50,5 +50,12 @@ void ToggleHostileTrapsView();
void SwitchMinesDrawModeForNetworks();
// ----------------------------- trait range display after this ----------------------------------------
// added by Flugente: display of ranges and areas of effects for traits
void DisplayTraitRange(const BOOLEAN& forceUpdate = FALSE);
void ToggleTraitRangeView(BOOLEAN fOn = TRUE);
void SetTraitToDisplay( UINT32 aTrait );
void SetGridNoForTraitDisplay( INT32 sGridNo );
#endif
+20
View File
@@ -2196,6 +2196,21 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
bNumRightIcons++;
}
// Flugente: icons for radio operator actions (not the assignment)
if ( MercPtrs[ pFace->ubSoldierID ]->bAssignment != RADIO_SCAN )
{
if ( MercPtrs[ pFace->ubSoldierID ]->bSoldierFlagMask & (SOLDIER_RADIO_OPERATOR_SCANNING|SOLDIER_RADIO_OPERATOR_LISTENING) )
{
DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 19 );
bNumRightIcons++;
}
else if ( MercPtrs[ pFace->ubSoldierID ]->bSoldierFlagMask & SOLDIER_RADIO_OPERATOR_JAMMING )
{
DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 20 );
bNumRightIcons++;
}
}
switch( pSoldier->bAssignment )
{
case DOCTOR:
@@ -2270,6 +2285,11 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
break;
case RADIO_SCAN:
sIconIndex_Assignment = 19;
fDoIcon_Assignment = TRUE;
break;
case MOVE_EQUIPMENT:
{
sIconIndex_Assignment = 15;
+81
View File
@@ -3946,6 +3946,23 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec
}
}
// Flugente: display energy level of power packs
if ( HasItemFlag(pObject->usItem, POWER_PACK) )
{
if ( OVERHEATING_MAX_TEMPERATURE > 0 )
{
FLOAT energylevel = (*pObject)[0]->data.bTemperature / (FLOAT)OVERHEATING_MAX_TEMPERATURE;
UINT32 red = (UINT32) ( 255 * ( 1.0 - max(0, 2*energylevel - 1.0) ) );
UINT32 green = (UINT32) ( 255 * ( min(1.0, 2*energylevel) ) );
UINT32 blue = 0;
UINT16 colour = Get16BPPColor( FROMRGB( red, green, blue ) );
DrawItemUIBarEx( pObject, DRAW_ITEM_TEMPERATURE, sX, sY + sHeight-1, ITEMDESC_ITEM_STATUS_WIDTH, sHeight-1, colour, colour, TRUE, guiSAVEBUFFER);
}
}
// display symbol if we are leaning our weapon on something
// display only if eapon resting is allowed, display is allowed, item is a gun/launcher, we are a person, we hold the gun in our hand, and we are resting the gun
if ( gGameExternalOptions.fWeaponResting && gGameExternalOptions.fDisplayWeaponRestingIndicator && pItem->usItemClass & (IC_GUN | IC_LAUNCHER) && pSoldier && &(pSoldier->inv[pSoldier->ubAttackingHand]) == pObject && pSoldier->IsWeaponMounted() )
@@ -6771,6 +6788,22 @@ void RenderItemDescriptionBox( )
DrawItemUIBarEx( &(*iter), DRAW_ITEM_TEMPERATURE, sCenX+4, sCenY, ITEM_BAR_WIDTH, ITEM_BAR_HEIGHT, colour, colour, TRUE, guiSAVEBUFFER );
}
// Flugente: display energy level of power packs
else if ( HasItemFlag(iter->usItem, POWER_PACK) )
{
if ( OVERHEATING_MAX_TEMPERATURE > 0 )
{
FLOAT energylevel = (*iter)[0]->data.bTemperature / (FLOAT)OVERHEATING_MAX_TEMPERATURE;
UINT32 red = (UINT32) ( 255 * ( 1.0 - max(0, 2*energylevel - 1.0) ) );
UINT32 green = (UINT32) ( 255 * ( min(1.0, 2*energylevel) ) );
UINT32 blue = 0;
UINT16 colour = Get16BPPColor( FROMRGB( red, green, blue ) );
DrawItemUIBarEx( &(*iter), DRAW_ITEM_TEMPERATURE, sCenX+4, sCenY, ITEM_BAR_WIDTH, ITEM_BAR_HEIGHT, colour, colour, TRUE, guiSAVEBUFFER );
}
}
}
}
@@ -7017,6 +7050,54 @@ void RenderItemDescriptionBox( )
mprintf( usX, usY, pStr );
}
}
else if ( HasItemFlag(gpItemDescObject->usItem, POWER_PACK) )
{
if ( OVERHEATING_MAX_TEMPERATURE > 0 )
{
FLOAT energylevel = (*gpItemDescObject)[0]->data.bTemperature / (FLOAT)OVERHEATING_MAX_TEMPERATURE;
UINT32 red = (UINT32) ( 255 * ( 1.0 - max(0, 2*energylevel - 1.0) ) );
UINT32 green = (UINT32) ( 255 * ( min(1.0, 2*energylevel) ) );
UINT32 blue = 0;
UINT8 stringNum = 5;
if ( energylevel > 0.8f )
stringNum = 1;
else if ( energylevel > 0.6f )
stringNum = 2;
else if ( energylevel > 0.4f )
stringNum = 3;
else if ( energylevel > 0.2f )
stringNum = 4;
// UDB system displays a string with colored condition text.
int regionindex = 7;
SetFontForeground( ForegroundColor );
swprintf( pStr, L"%s", gPowerPackDesc[STR_POWERPACK_BEGIN] ); // "Temperature is "
mprintf( gItemDescTextRegions[regionindex].sLeft, gItemDescTextRegions[regionindex].sTop, pStr );
// Record length
INT16 indent = StringPixLength( gPowerPackDesc[STR_POWERPACK_BEGIN], ITEMDESC_FONT );
swprintf( pStr, L"%s", gPowerPackDesc[stringNum] );
SetRGBFontForeground( red, green, blue );
mprintf( gItemDescTextRegions[regionindex].sLeft+indent+2, gItemDescTextRegions[regionindex].sTop, pStr );
// Record length
indent += StringPixLength( gPowerPackDesc[stringNum], ITEMDESC_FONT );
SetFontForeground( ForegroundColor );
swprintf( pStr, L"%s", gPowerPackDesc[STR_POWERPACK_END] ); // "."
mprintf( gItemDescTextRegions[regionindex].sLeft + indent + 2, gItemDescTextRegions[regionindex].sTop, pStr );
// to get the text to the left side...
swprintf( pStr, L"");
FindFontRightCoordinates( gItemDescTextRegions[regionindex].sLeft, gItemDescTextRegions[regionindex].sTop, gItemDescTextRegions[regionindex].sRight - gItemDescTextRegions[regionindex].sLeft ,gItemDescTextRegions[regionindex].sBottom - gItemDescTextRegions[regionindex].sTop ,pStr, BLOCKFONT2, &usX, &usY);
mprintf( usX, usY, pStr );
}
}
// UDB system displays a string with colored condition text.
SetFontForeground( ForegroundColor );
+7
View File
@@ -508,6 +508,13 @@ void DrawItemUIBarEx( OBJECTTYPE *pObject, UINT8 ubStatus, INT16 sXPos, INT16 sY
{
sValue = 100;
}
else if ( HasItemFlag(pObject->usItem, POWER_PACK) )
{
if ( OVERHEATING_MAX_TEMPERATURE > 0 )
{
sValue = (INT16) ( 100 * (*pObject)[0]->data.bTemperature / (FLOAT)OVERHEATING_MAX_TEMPERATURE );
}
}
else
{
sValue = (INT16) (100 * GetGunOverheatJamPercentage( pObject) );
+12 -7
View File
@@ -714,10 +714,10 @@ extern OBJECTTYPE gTempObject;
#define TRIPWIRE_NETWORK_LVL_3 0x00400000 //4194304
#define TRIPWIRE_NETWORK_LVL_4 0x00800000 //8388608
/*#define TRIPWIRE_NETWORK_LVL_1 0x01000000 //16777216
#define TRIPWIRE_NETWORK_LVL_2 0x02000000 //33554432
#define TRIPWIRE_NETWORK_LVL_3 0x04000000 //67108864
#define TRIPWIRE_NETWORK_LVL_4 0x08000000 //134217728
#define ARTILLERY_STRIKE_COUNT_1 0x01000000 //16777216
#define ARTILLERY_STRIKE_COUNT_2 0x02000000 //33554432
#define ARTILLERY_STRIKE_COUNT_4 0x04000000 //67108864
/*#define TRIPWIRE_NETWORK_LVL_4 0x08000000 //134217728
#define PLAYER_NET_1_LVL_4 0x10000000 //268435456
#define PLAYER_NET_2_LVL_4 0x20000000 //536870912
@@ -725,6 +725,8 @@ extern OBJECTTYPE gTempObject;
#define PLAYER_NET_4_LVL_4 0x80000000 //2147483648*/
// ----------------------------------------------------------------
#define ANY_ARTILLERY_FLAG (ARTILLERY_STRIKE_COUNT_1|ARTILLERY_STRIKE_COUNT_2|ARTILLERY_STRIKE_COUNT_4)
// -------- added by Flugente: various item flags --------
// flags used for various item properties (easier than adding 32 differently named variables). DO NOT CHANGE THEM, UNLESS YOU KNOW WHAT YOU ARE DOING!!!
// note that these should not be used to determine what kind of an attachment an item is, that is determined by attachmentclass and the AC_xxx flags above
@@ -759,9 +761,9 @@ extern OBJECTTYPE gTempObject;
#define SCUBA_FINS 0x00800000 //8388608 // this item speed up swimming, but slows walking and running
#define TRIPWIREROLL 0x01000000 //16777216 // this item is a tripwire roll
/*#define PLAYER_NET_2_LVL_3 0x02000000 //33554432
#define PLAYER_NET_3_LVL_3 0x04000000 //67108864
#define PLAYER_NET_4_LVL_3 0x08000000 //134217728
#define RADIO_SET 0x02000000 //33554432 // item can be used to radio militia/squads in other sectors
#define SIGNAL_SHELL 0x04000000 //67108864 // this is a signal shell that precedes artillery barrages
#define POWER_PACK 0x08000000 //134217728 // item continously powers an item it is attached to
#define PLAYER_NET_1_LVL_4 0x10000000 //268435456
#define PLAYER_NET_2_LVL_4 0x20000000 //536870912
@@ -1856,6 +1858,9 @@ enum
IMP_COVERT,
IMP_COVERT_EXP,
// Flugente: added radio operator
IMP_RADIO_OPERATOR,
MAX_IMP_ITEM_TYPES
};
+6
View File
@@ -7822,6 +7822,12 @@ BOOLEAN CreateItem( UINT16 usItem, INT16 bStatus, OBJECTTYPE * pObj )
(*pObj)[0]->data.bTemperature = OVERHEATING_MAX_TEMPERATURE;
}
// Flugente: certain items get the maximum temperature when they are created
if ( HasItemFlag(usItem, POWER_PACK) )
{
(*pObj)[0]->data.bTemperature = (FLOAT)(OVERHEATING_MAX_TEMPERATURE);
}
//ADB ubWeight has been removed, see comments in OBJECTTYPE
//pObj->ubWeight = CalculateObjectWeight( pObj );
fRet = TRUE;
+1
View File
@@ -494,6 +494,7 @@ typedef struct
UINT8 usWaterType; // type of water source in this sector
UINT16 usNaturalDirt; // extra dirt percentage when firing in this sector
UINT8 usCurfewValue; // determines wether mercs disguising as civilian are automatically discovered (certain sectors are 'restricted' to civilians)
INT8 sRadioScanModifier; // modifies the scan range of the radio scan assignment in this sector
UINT16 usPrisonRoomNumber[MAX_PRISON_ROOMS]; // room numbers of prisons
} SECTOR_EXT_DATA;
+7 -2
View File
@@ -1009,7 +1009,8 @@ void HandleShadingOfLinesForMilitiaControlMenu( void )
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
// Check LOS!
if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pTMilitiaSoldier->sGridNo, pTMilitiaSoldier->pathing.bLevel, 3, TRUE, CALC_FROM_ALL_DIRS ) )
// Flugente: active radio sets allows us to give individual orders even without a line of sight
if ( pSoldier->CanUseRadio() || SoldierTo3DLocationLineOfSightTest( pSoldier, pTMilitiaSoldier->sGridNo, pTMilitiaSoldier->pathing.bLevel, 3, TRUE, CALC_FROM_ALL_DIRS ) )
{
UnShadeStringInBox( ghMilitiaControlBox, MILCON_MENU_ATTACK );
UnShadeStringInBox( ghMilitiaControlBox, MILCON_MENU_HOLD );
@@ -1069,7 +1070,11 @@ BOOLEAN CheckIfRadioIsEquipped( void )
//pSoldier = GetSelectedAssignSoldier( FALSE ); //do not use
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
{
// Flugente: active radio sets also count as radio
if ( pSoldier->CanUseRadio() )
return TRUE;
//bSlot = FindObj( pSoldier, EXTENDEDEAR );
bSlot = FindHearingAid(pSoldier);
//ScreenMsg( FONT_WHITE, MSG_INTERFACE, L"Position: %d", bSlot );
+677
View File
@@ -0,0 +1,677 @@
/**
* @file
* @author Flugente (bears-pit.com)
*/
#include "SkillMenu.h"
#include "Soldier Profile Type.h"
#include "Overhead.h"
#include "Text.h"
#include "Isometric Utils.h"
#include "DisplayCover.h"
#include "worldman.h"
UINT16 usTraitMenuPosX = 0;
UINT16 usTraitMenuPosY = 0;
INT32 sTraitsMenuTargetGridNo = NOWHERE;
void Hide( void )
{
// set off display of trait range/target gridno
ToggleTraitRangeView(FALSE);
// Dirty!
fMapPanelDirty = TRUE;
}
// Turns an option off by always returning FALSE
BOOLEAN Popup_OptionOff( void ) { return FALSE; }
void
SkillMenuItem::SetupPopup(CHAR* name)
{
// create a popup
gPopup = new POPUP(name);
// add a callback that lets the keyboard handler know we're done (and ready to pop up again)
gPopup->setCallback(POPUP_CALLBACK_HIDE, new popupCallbackFunction<void, void>( &Hide ) );
}
// Different SkillItem classes. We need wrappers for each one, as we cannot pass a pointer to a member function (we need a concrete object)
/////////////////////////////// Trait Selection ////////////////////////////////////////////
TraitSelection gTraitSelection;
//void Wrapper_Function_TraitSelection( UINT32 aVal) { gTraitSelection.Functions(aVal); }
void Wrapper_Setup_TraitSelection( UINT32 aVal) { gTraitSelection.Setup(aVal); }
void Wrapper_Cancel_TraitSelection( UINT32 aVal ) { gTraitSelection.Cancel(); }
/////////////////////////////// Trait Selection ////////////////////////////////////////////
/////////////////////////////// Skill Selection ////////////////////////////////////////////
SkillSelection gSkillSelection;
void Wrapper_Function_SkillSelection( UINT32 aVal) { gSkillSelection.Functions(aVal); }
void Wrapper_Setup_SkillSelection( UINT32 aVal) { gSkillSelection.Setup(aVal); }
void Wrapper_Cancel_SkillSelection( UINT32 aVal ) { gSkillSelection.Cancel(); }
/////////////////////////////// Skill Selection ////////////////////////////////////////////
/////////////////////////////// Artillery Sector Selection ////////////////////////////////////////////
ArtillerySector gArtillerySector;
//void Wrapper_Function_ArtillerySector( UINT32 aVal) { gArtillerySector.Functions(aVal); }
void Wrapper_Setup_ArtillerySector( UINT32 aVal) { gArtillerySector.Setup(aVal); }
void Wrapper_Cancel_ArtillerySector( UINT32 aVal ) { gArtillerySector.Cancel(); }
/////////////////////////////// Artillery Sector Selection ////////////////////////////////////////////
/////////////////////////////// Artillery Team Selection ////////////////////////////////////////////
ArtilleryTeam gArtilleryTeam;
void Wrapper_Function_ArtilleryTeam( UINT32 aVal) { gArtilleryTeam.Functions(aVal); }
void Wrapper_Setup_ArtilleryTeam( UINT32 aVal) { gArtilleryTeam.Setup(aVal); }
void Wrapper_Cancel_ArtilleryTeam( UINT32 aVal ) { gArtilleryTeam.Cancel(); }
/////////////////////////////// Artillery Team Selection ////////////////////////////////////////////
/////////////////////////////// Reinforcement Sector Selection ////////////////////////////////////////////
ReinforcementSector gReinforcementSector;
//void Wrapper_Function_ReinforcementSector( UINT32 aVal) { gReinforcementSector.Functions(aVal); }
void Wrapper_Setup_ReinforcementSector( UINT32 aVal) { gReinforcementSector.Setup(aVal); }
void Wrapper_Cancel_ReinforcementSector( UINT32 aVal ) { gReinforcementSector.Cancel(); }
/////////////////////////////// Reinforcement Sector Selection ////////////////////////////////////////////
/////////////////////////////// Reinforcement Number Selection ////////////////////////////////////////////
ReinforcementNumber gReinforcementNumber;
void Wrapper_Function_ReinforcementNumber( UINT32 aVal) { gReinforcementNumber.Functions(aVal); }
void Wrapper_Setup_ReinforcementNumber( UINT32 aVal) { gReinforcementNumber.Setup(aVal); }
void Wrapper_Cancel_ReinforcementNumber( UINT32 aVal ) { gReinforcementNumber.Cancel(); }
/////////////////////////////// Reinforcement Number Selection ////////////////////////////////////////////
/////////////////////////////// Soldier Target Selection ////////////////////////////////////////////
SoldierSelection gSoldierSelection;
void Wrapper_Function_SoldierSelection( UINT32 aVal) { gSoldierSelection.Functions(aVal); }
void Wrapper_Setup_SoldierSelection( UINT32 aVal) { gSoldierSelection.Setup(aVal); }
void Wrapper_Cancel_SoldierSelection( UINT32 aVal ) { gSoldierSelection.Cancel(); }
/////////////////////////////// Soldier Target Selection ////////////////////////////////////////////
/////////////////////////////// Trait Selection ////////////////////////////////////////////
void
TraitSelection::Setup( UINT32 aVal )
{
Destroy();
SOLDIERTYPE * pSoldier = NULL;
GetSoldier( &pSoldier, gusSelectedSoldier );
if ( pSoldier == NULL )
return;
SetupPopup("TraitSelection");
POPUP_OPTION *pOption;
CHAR16 pStr[300];
// create entries for the sub-menus for each trait
const UINT8 num = 1;
UINT8 traitarray[num];
traitarray[0] = RADIO_OPERATOR_NT;
for ( int i = 0; i < num; ++i)
{
swprintf( pStr, gzMercSkillTextNew[traitarray[i]] );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void,UINT32>( &Wrapper_Setup_SkillSelection, traitarray[i] ) );
// if we cannot perform this skill, grey it out
if ( !HAS_SKILL_TRAIT(pSoldier, traitarray[i]) )
{
// Set this option off.
pOption->setAvail(new popupCallbackFunction<bool,void*>( &Popup_OptionOff, NULL ));
}
GetPopup()->addOption( *pOption );
}
// cancel option
swprintf( pStr, L"Cancel" );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void,UINT32>( &Wrapper_Cancel_TraitSelection, 0 ) );
GetPopup()->addOption( *pOption );
// grab soldier's x,y screen position
INT16 sX, sY;
GetSoldierScreenPos( pSoldier, &sX, &sY );
if( sX < 0 ) sX = 0;
if( sY < 0 ) sY = 0;
usTraitMenuPosX = sX + 30;
usTraitMenuPosY = sY;
if ( ( usTraitMenuPosX + 400 ) > SCREEN_WIDTH )
usTraitMenuPosX = SCREEN_WIDTH - 400;
if ( ( usTraitMenuPosY + 130 ) > SCREEN_HEIGHT )
usTraitMenuPosY = SCREEN_HEIGHT - 190;
SetPos(usTraitMenuPosX, usTraitMenuPosY);
}
/////////////////////////////// Trait Selection ////////////////////////////////////////////
/////////////////////////////// Skill Selection ////////////////////////////////////////////
void
SkillSelection::Setup( UINT32 aVal )
{
Destroy();
SOLDIERTYPE * pSoldier = NULL;
GetSoldier( &pSoldier, gusSelectedSoldier );
if ( pSoldier == NULL )
return;
if ( HAS_SKILL_TRAIT(pSoldier, aVal) )
{
SetupPopup("SkillSelection");
POPUP_OPTION *pOption;
CHAR16 pStr[300];
SetTraitToDisplay(aVal);
SetGridNoForTraitDisplay(sTraitsMenuTargetGridNo);
// this switch isn't really necessary. But dividing the skills into menus for each trait gives a better overview, and looks way better than a huge list
switch ( aVal )
{
case RADIO_OPERATOR_NT:
{
for(UINT32 uiCounter = SKILLS_RADIO_FIRST; uiCounter <= SKILLS_RADIO_LAST; ++uiCounter)
{
swprintf( pStr, pTraitSkillsMenuStrings[uiCounter] );
if ( uiCounter == SKILLS_RADIO_ARTILLERY)
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void,UINT32>( &Wrapper_Setup_ArtillerySector, uiCounter ) );
else if ( uiCounter == SKILLS_RADIO_CALLREINFORCEMENTS)
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void,UINT32>( &Wrapper_Setup_ReinforcementSector, uiCounter ) );
else
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void,UINT32>( &Wrapper_Function_SkillSelection, uiCounter ) );
// if we cannot perform this skill, grey it out
if ( !(pSoldier->CanUseSkill(uiCounter, TRUE)) )
{
// Set this option off.
pOption->setAvail(new popupCallbackFunction<bool,void*>( &Popup_OptionOff, NULL ));
}
GetPopup()->addOption( *pOption );
}
}
break;
default:
break;
}
// certain traits have skills whose effects depend on wether eomeone is near to us (squadleader, commissar). We therefore display our radius of effect while this display is open
ToggleTraitRangeView(TRUE);
// cancel option
swprintf( pStr, L"Cancel" );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void,UINT32>( &Wrapper_Cancel_SkillSelection, 0 ) );
GetPopup()->addOption( *pOption );
}
// same y, different x
SetPos(gTraitSelection.GetMaxPosX(), usTraitMenuPosY);
if ( HAS_SKILL_TRAIT(pSoldier, aVal) )
{
UINT8 cnt = 0;
switch ( aVal )
{
case RADIO_OPERATOR_NT:
{
for(UINT32 uiCounter = SKILLS_RADIO_FIRST; uiCounter <= SKILLS_RADIO_LAST; ++uiCounter)
{
SetRegionFastHelpText( &(GetPopup()->MenuRegion[cnt++]), pSoldier->PrintSkillDesc(uiCounter) );
}
}
break;
}
}
}
void
SkillSelection::Functions( UINT32 aVal )
{
Cancel();
SOLDIERTYPE * pSoldier = NULL;
GetSoldier( &pSoldier, gusSelectedSoldier );
if ( pSoldier == NULL )
return;
UINT8 ubID = WhoIsThere2(sTraitsMenuTargetGridNo, 0 );
pSoldier->UseSkill(aVal, sTraitsMenuTargetGridNo, ubID);
Cancel();
gTraitSelection.Cancel();
}
/////////////////////////////// Skill Selection ////////////////////////////////////////////
/////////////////////////////// Artillery Sector Selection ////////////////////////////////////////////
void
ArtillerySector::Setup( UINT32 aVal )
{
Destroy();
SOLDIERTYPE * pSoldier = NULL;
GetSoldier( &pSoldier, gusSelectedSoldier );
if ( pSoldier == NULL )
return;
if ( pSoldier->CanUseSkill(SKILLS_RADIO_ARTILLERY) )
{
SetupPopup("ArtillerySector");
POPUP_OPTION *pOption;
CHAR16 pStr[300];
// check wether we can call artillery from the 4 adjacent sectors
for (UINT8 i = 0; i < 4; ++i)
{
INT16 loopX = pSoldier->sSectorX;
INT16 loopY = pSoldier->sSectorY;
if ( i == 0 ) ++loopY;
else if ( i == 1 ) ++loopX;
else if ( i == 2 ) --loopY;
else if ( i == 3 ) --loopX;
if ( loopX < 1 || loopX >= MAP_WORLD_X - 1 || loopY < 1 || loopY >= MAP_WORLD_Y - 1 )
continue;
UINT32 sectornr = (UINT32)SECTOR( loopX, loopY );
swprintf( pStr, L"%c%d", loopY + 'A' - 1, loopX );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Setup_ArtilleryTeam, sectornr ) );
// grey out if no artillery can be called from this sector
if ( !IsValidArtilleryOrderSector( loopX, loopY, pSoldier->bSectorZ, pSoldier->bTeam ) && !IsValidArtilleryOrderSector( loopX, loopY, pSoldier->bSectorZ, MILITIA_TEAM ) )
{
// Set this option off.
pOption->setAvail(new popupCallbackFunction<bool,void*>( &Popup_OptionOff, NULL ));
}
GetPopup()->addOption( *pOption );
}
// cancel option
swprintf( pStr, L"Cancel" );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void,UINT32>( &Wrapper_Cancel_ArtillerySector, 0 ) );
GetPopup()->addOption( *pOption );
}
// same y, different x
SetPos(gSkillSelection.GetMaxPosX(), usTraitMenuPosY);
}
/////////////////////////////// Artillery Sector Selection ////////////////////////////////////////////
/////////////////////////////// Artillery Team Selection ////////////////////////////////////////////
void
ArtilleryTeam::Setup( UINT32 aVal )
{
Destroy();
SOLDIERTYPE * pSoldier = NULL;
GetSoldier( &pSoldier, gusSelectedSoldier );
if ( pSoldier == NULL )
return;
if ( pSoldier->CanUseSkill(SKILLS_RADIO_ARTILLERY) && pSoldier->bSectorZ == 0)
{
usSector = aVal;
SetupPopup("ArtilleryTeam");
POPUP_OPTION *pOption;
CHAR16 pStr[300];
// determine sector coordinates
INT16 sSectorX = SECTORX(usSector);
INT16 sSectorY = SECTORY(usSector);
// order artillery from militia
swprintf( pStr, L"Militia" );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Function_ArtilleryTeam, MILITIA_TEAM ) );
// grey out if no ArtilleryTeam can be called from this sector
if ( !IsValidArtilleryOrderSector( sSectorX, sSectorY, pSoldier->bSectorZ, MILITIA_TEAM ) )
{
// Set this option off.
pOption->setAvail(new popupCallbackFunction<bool,void*>( &Popup_OptionOff, NULL ));
}
GetPopup()->addOption( *pOption );
// order artillery from our mercs
swprintf( pStr, L"Other Squads" );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void, INT8>( &Wrapper_Function_ArtilleryTeam, pSoldier->bTeam ) );
// grey out if no ArtilleryTeam can be called from this sector
if ( !IsValidArtilleryOrderSector( sSectorX, sSectorY, pSoldier->bSectorZ, pSoldier->bTeam ) )
{
// Set this option off.
pOption->setAvail(new popupCallbackFunction<bool,void*>( &Popup_OptionOff, NULL ));
}
GetPopup()->addOption( *pOption );
// cancel option
swprintf( pStr, L"Cancel" );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void,UINT32>( &Wrapper_Cancel_ArtilleryTeam, 0 ) );
GetPopup()->addOption( *pOption );
}
// same y, different x
SetPos(gArtillerySector.GetMaxPosX(), usTraitMenuPosY);
}
void
ArtilleryTeam::Functions( UINT32 aVal )
{
Cancel();
SOLDIERTYPE * pSoldier = NULL;
GetSoldier( &pSoldier, gusSelectedSoldier );
if ( pSoldier == NULL || !pSoldier->CanUseSkill(SKILLS_RADIO_ARTILLERY) )
return;
pSoldier->OrderArtilleryStrike(usSector, sTraitsMenuTargetGridNo, (UINT8)(aVal));
Cancel();
gArtillerySector.Cancel();
gSkillSelection.Cancel();
gTraitSelection.Cancel();
}
/////////////////////////////// Artillery Team Selection ////////////////////////////////////////////
/////////////////////////////// Reinforcement Sector Selection ////////////////////////////////////////////
extern UINT8 CountAllMilitiaInSector(INT16 sMapX, INT16 sMapY);
void
ReinforcementSector::Setup( UINT32 aVal )
{
Destroy();
SOLDIERTYPE * pSoldier = NULL;
GetSoldier( &pSoldier, gusSelectedSoldier );
if ( pSoldier == NULL )
return;
if ( pSoldier->CanUseSkill(aVal) )
{
SetupPopup("Reinforcements sector");
POPUP_OPTION *pOption;
CHAR16 pStr[300];
// check wether we can call artillery from the 4 adjacent sectors
for (UINT8 i = 0; i < 4; ++i)
{
INT16 loopX = pSoldier->sSectorX;
INT16 loopY = pSoldier->sSectorY;
if ( i == 0 ) ++loopY;
else if ( i == 1 ) ++loopX;
else if ( i == 2 ) --loopY;
else if ( i == 3 ) --loopX;
if ( loopX < 1 || loopX >= MAP_WORLD_X - 1 || loopY < 1 || loopY >= MAP_WORLD_Y - 1 )
continue;
UINT32 sectornr = (UINT32)SECTOR( loopX, loopY );
swprintf( pStr, L"%c%d", loopY + 'A' - 1, loopX );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Setup_ReinforcementNumber, sectornr ) );
// grey out if no reinforcements can be called from this sector
if( !CountAllMilitiaInSector( loopX, loopY ) )
{
// Set this option off.
pOption->setAvail(new popupCallbackFunction<bool,void*>( &Popup_OptionOff, NULL ));
}
GetPopup()->addOption( *pOption );
}
// cancel option
swprintf( pStr, L"Cancel" );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Cancel_ReinforcementSector, 0 ) );
GetPopup()->addOption( *pOption );
}
// same y, different x
SetPos(gSkillSelection.GetMaxPosX(), usTraitMenuPosY);
}
/////////////////////////////// Reinforcement Sector Selection ////////////////////////////////////////////
/////////////////////////////// Reinforcement Number Selection ////////////////////////////////////////////
void
ReinforcementNumber::Setup( UINT32 aVal )
{
Destroy();
SOLDIERTYPE * pSoldier = NULL;
GetSoldier( &pSoldier, gusSelectedSoldier );
if ( pSoldier == NULL )
return;
if ( pSoldier->CanUseSkill(SKILLS_RADIO_CALLREINFORCEMENTS) )
{
usSector = aVal;
SetupPopup("Reinforcements number submenu");
POPUP_OPTION *pOption;
CHAR16 pStr[300];
UINT8 numberofmilitia = CountAllMilitiaInSector( SECTORX(usSector), SECTORY(usSector) );
// 5 militia option
swprintf( pStr, L"5 Militia" );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Function_ReinforcementNumber, 5 ) );
if ( numberofmilitia < 5 )
{
// Set this option off.
pOption->setAvail(new popupCallbackFunction<bool,void*>( &Popup_OptionOff, NULL ));
}
GetPopup()->addOption( *pOption );
// 10 militia option
swprintf( pStr, L"10 Militia" );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Function_ReinforcementNumber, 10 ) );
if ( numberofmilitia < 10 )
{
// Set this option off.
pOption->setAvail(new popupCallbackFunction<bool,void*>( &Popup_OptionOff, NULL ));
}
GetPopup()->addOption( *pOption );
// 15 militia option
swprintf( pStr, L"15 Militia" );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Function_ReinforcementNumber, 15 ) );
if ( numberofmilitia < 15 )
{
// Set this option off.
pOption->setAvail(new popupCallbackFunction<bool,void*>( &Popup_OptionOff, NULL ));
}
GetPopup()->addOption( *pOption );
// 20 militia option
swprintf( pStr, L"20 Militia" );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Function_ReinforcementNumber, 20 ) );
if ( numberofmilitia < 20 )
{
// Set this option off.
pOption->setAvail(new popupCallbackFunction<bool,void*>( &Popup_OptionOff, NULL ));
}
GetPopup()->addOption( *pOption );
// all militia option
swprintf( pStr, L"All Militia" );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Function_ReinforcementNumber, numberofmilitia ) );
GetPopup()->addOption( *pOption );
// cancel option
swprintf( pStr, L"Cancel" );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Cancel_ReinforcementNumber, 0 ) );
GetPopup()->addOption( *pOption );
}
// same y, different x
SetPos(gReinforcementSector.GetMaxPosX(), usTraitMenuPosY);
}
void
ReinforcementNumber::Functions( UINT32 aVal )
{
Cancel();
SOLDIERTYPE * pSoldier = NULL;
GetSoldier( &pSoldier, gusSelectedSoldier );
if ( pSoldier == NULL || !pSoldier->CanUseSkill(SKILLS_RADIO_CALLREINFORCEMENTS) )
return;
pSoldier->RadioCallReinforcements(usSector, aVal);
Cancel();
gReinforcementSector.Cancel();
gSkillSelection.Cancel();
gTraitSelection.Cancel();
}
/////////////////////////////// Reinforcement Number Selection ////////////////////////////////////////////
/////////////////////////////// Soldier Target Selection ////////////////////////////////////////////
void
SoldierSelection::Setup( UINT32 aVal )
{
Destroy();
SOLDIERTYPE * pSoldier = NULL;
GetSoldier( &pSoldier, gusSelectedSoldier );
if ( pSoldier == NULL )
return;
if ( pSoldier->CanUseSkill(aVal) )
{
usSkill = aVal;
SetupPopup("SoldierSelection");
POPUP_OPTION *pOption;
CHAR16 pStr[300];
// pretty simple: we find every soldier in a radius around the target position and add him to the list
// loop through all soldiers around
for ( UINT32 cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID ; cnt <= gTacticalStatus.Team[ CIV_TEAM ].bLastID ; ++cnt )
{
INT32 iRange = GetRangeInCellCoordsFromGridNoDiff( sTraitsMenuTargetGridNo, MercPtrs[ cnt ]->sGridNo );
if ( iRange < 100 )
{
if ( cnt != pSoldier->ubID )
{
swprintf( pStr, L"%s", MercPtrs[ cnt ]->GetName() );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void, UINT8>( &Wrapper_Function_SoldierSelection, cnt ) );
// grey out if no artillery can be called from this sector
if ( 0 )
{
// Set this option off.
pOption->setAvail(new popupCallbackFunction<bool,void*>( &Popup_OptionOff, NULL ));
}
GetPopup()->addOption( *pOption );
}
}
}
// cancel option
swprintf( pStr, L"Cancel" );
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void,UINT32>( &Wrapper_Cancel_SoldierSelection, 0 ) );
GetPopup()->addOption( *pOption );
}
// same y, different x
SetPos(gSkillSelection.GetMaxPosX(), usTraitMenuPosY);
}
void
SoldierSelection::Functions( UINT32 aVal )
{
Cancel();
SOLDIERTYPE * pSoldier = NULL;
GetSoldier( &pSoldier, gusSelectedSoldier );
if ( pSoldier == NULL )
return;
pSoldier->UseSkill(usSkill, sTraitsMenuTargetGridNo, aVal);
Cancel();
gSkillSelection.Cancel();
gTraitSelection.Cancel();
}
/////////////////////////////// Soldier Target Selection ////////////////////////////////////////////
/**
* Flugente: traits menu popup box
* This will create other boxes when needed
*/
void TraitsMenu( INT32 usMapPos )
{
sTraitsMenuTargetGridNo = usMapPos;
gTraitSelection.Setup(0);
}
+165
View File
@@ -0,0 +1,165 @@
#ifndef _SKILL_MENU_
#define _SKILL_MENU_
/**
* @file
* @author Flugente (bears-pit.com)
*/
#include "popup_class.h"
/**
* @brief A basic class for popup menus
* Use this to create mensu calling other menus, each having various sub-options
* I tried to make this as orderly as possible. It's ugly, but much more clean than the first solution, which was a hardcoded mess.
* You will, however, still need wrapper functions (we use callbacks on member functions), see Implementation.
*/
class SkillMenuItem
{
public:
SkillMenuItem() :
fInitialized(FALSE), usPosX(0), gPopup(NULL)
{
}
virtual void Cancel()
{
// Hide the Filter Menu pop-up.
if (gPopup != NULL && fInitialized )
{
gPopup->hide();
}
}
virtual void Destroy()
{
// If we already have a popup, destroy it first. This ensures we get a fresh menu each time.
if ( fInitialized )
{
delete(gPopup);
gPopup = NULL;
fInitialized = FALSE;
}
}
UINT16 GetMaxPosX()
{
if ( gPopup )
return (usPosX + gPopup->getBoxDimensions().iRight);
return usPosX;
}
virtual void SetPos(UINT16 usX, UINT16 usY)
{
// same y, different x
usPosX = usX;
gPopup->setPosition( usPosX, usY );
fInitialized = TRUE;
gPopup->show();
}
void SetupPopup(CHAR* name);
POPUP* GetPopup()
{
return gPopup;
}
virtual void Setup( UINT32 aVal ) {}
virtual void Functions( UINT32 aVal ) {}
private:
BOOLEAN fInitialized;
UINT16 usPosX;
POPUP* gPopup;
};
// select a trait
class TraitSelection : public SkillMenuItem
{
public:
TraitSelection() {}
void Setup( UINT32 aVal );
};
// select a skill
class SkillSelection : public SkillMenuItem
{
public:
SkillSelection() : usSector(0) {}
void Setup( UINT32 aVal );
void Functions( UINT32 aVal );
private:
UINT32 usSector;
};
// select sector to call artillery from
class ArtillerySector : public SkillMenuItem
{
public:
ArtillerySector() {}
void Setup( UINT32 aVal );
};
// select team we request artillery from
class ArtilleryTeam : public SkillMenuItem
{
public:
ArtilleryTeam() : usSector(0) {}
void Setup( UINT32 aVal );
void Functions( UINT32 aVal );
private:
UINT32 usSector;
};
// select the sector we call reinforcements from
class ReinforcementSector : public SkillMenuItem
{
public:
ReinforcementSector() {}
void Setup( UINT32 aVal );
};
// select the number of milita that should reinforce
class ReinforcementNumber : public SkillMenuItem
{
public:
ReinforcementNumber() : usSector(0) {}
void Setup( UINT32 aVal );
void Functions( UINT32 aVal );
private:
UINT32 usSector;
};
// select an individual soldier as target of a skill
class SoldierSelection : public SkillMenuItem
{
public:
SoldierSelection() : usSkill(0) {}
void Setup( UINT32 aVal );
void Functions( UINT32 aVal );
private:
UINT32 usSkill;
};
/**
* Flugente: traits menu popup box
* This will create other boxes when needed
*/
void TraitsMenu( INT32 usMapPos );
#endif
File diff suppressed because it is too large Load Diff
+98 -26
View File
@@ -353,34 +353,34 @@ enum
// -------- added by Flugente: various flags for soldiers --------
// easier than adding 32 differently named variables. DO NOT CHANGE THEM, UNLESS YOU KNOW WHAT YOU ARE DOING!!!
#define SOLDIER_DRUGGED 0x00000001 //1 // Soldier is on drugs
#define SOLDIER_NO_AP 0x00000002 //2 // Soldier has no APs this turn (fix for reinforcement bug)
#define SOLDIER_COVERT_CIV 0x00000004 //4 // Soldier is currently disguised as a civilian
#define SOLDIER_COVERT_SOLDIER 0x00000008 //8 // Soldier is currently disguised as an enemy soldier
#define SOLDIER_DRUGGED 0x00000001 //1 // Soldier is on drugs
#define SOLDIER_NO_AP 0x00000002 //2 // Soldier has no APs this turn (fix for reinforcement bug)
#define SOLDIER_COVERT_CIV 0x00000004 //4 // Soldier is currently disguised as a civilian
#define SOLDIER_COVERT_SOLDIER 0x00000008 //8 // Soldier is currently disguised as an enemy soldier
#define SOLDIER_DAMAGED_VEST 0x00000010 //16 // Soldier's vest is damaged (and thus can't be taken off)
#define SOLDIER_COVERT_NPC_SPECIAL 0x00000020 //32 // Special flag for NPCs when recruited (used for covert stuff)
#define SOLDIER_NEW_VEST 0x00000040 //64 // Soldier is wearing new vest. if having both vest and pants, he can disguise
#define SOLDIER_NEW_PANTS 0x00000080 //128 // Soldier is wearing new pants
#define SOLDIER_DAMAGED_VEST 0x00000010 //16 // Soldier's vest is damaged (and thus can't be taken off)
#define SOLDIER_COVERT_NPC_SPECIAL 0x00000020 //32 // Special flag for NPCs when recruited (used for covert stuff)
#define SOLDIER_NEW_VEST 0x00000040 //64 // Soldier is wearing new vest. if having both vest and pants, he can disguise
#define SOLDIER_NEW_PANTS 0x00000080 //128 // Soldier is wearing new pants
#define SOLDIER_DAMAGED_PANTS 0x00000100 //256 // Soldier's vest is damaged (and thus can't be taken off)
#define SOLDIER_HEADSHOT 0x00000200 //512 // last hit received was a headshot (attack to the head, so knifes/punches also work)
#define SOLDIER_POW 0x00000400 //1024 // we are a prisoner of war
#define SOLDIER_ASSASSIN 0x00000800 //2048 // we are an enemy assassin, and thus we will behave very different from normal enemies
#define SOLDIER_DAMAGED_PANTS 0x00000100 //256 // Soldier's vest is damaged (and thus can't be taken off)
#define SOLDIER_HEADSHOT 0x00000200 //512 // last hit received was a headshot (attack to the head, so knifes/punches also work)
#define SOLDIER_POW 0x00000400 //1024 // we are a prisoner of war
#define SOLDIER_ASSASSIN 0x00000800 //2048 // we are an enemy assassin, and thus we will behave very different from normal enemies
#define SOLDIER_POW_PRISON 0x00001000 //4096 // this guy is a prisoner of war in a prison sector. SOLDIER_POW refers to people we capture, this refers to people we hold captive
#define SOLDIER_EQUIPMENT_DROPPED 0x00002000 //8192 // under certain circumstances, militia can be ordered to drop their gear twice. Thus we set a marker to avoid that.
#define SOLDIER_ACCESSTEAMMEMBER 0x00004000 //16384 // this merc is accessing another team member'S inventory (via abusing the stealing mechanic)
#define SOLDIER_REDOFLASHLIGHT 0x00008000 //32768 // this flag signifies that we somehow interacted with the items in our hands. Thus we have to possible redo lighting from flashlights
#define SOLDIER_POW_PRISON 0x00001000 //4096 // this guy is a prisoner of war in a prison sector. SOLDIER_POW refers to people we capture, this refers to people we hold captive
#define SOLDIER_EQUIPMENT_DROPPED 0x00002000 //8192 // under certain circumstances, militia can be ordered to drop their gear twice. Thus we set a marker to avoid that.
#define SOLDIER_ACCESSTEAMMEMBER 0x00004000 //16384 // this merc is accessing another team member'S inventory (via abusing the stealing mechanic)
#define SOLDIER_REDOFLASHLIGHT 0x00008000 //32768 // this flag signifies that we somehow interacted with the items in our hands. Thus we have to possible redo lighting from flashlights
#define SOLDIER_LIGHT_OWNER 0x00010000 //65536 // we 'own' at least one light source (via flashlights)
#define SOLDIER_AIRDROP_BONUS 0x00020000 //131072 // backgrounds: special AP bonus during the first turn of an airdrop
#define SOLDIER_ASSAULT_BONUS 0x00040000 //262144 // backgrounds: our first turn in an assault
/*#define PLAYER_NET_4_LVL_1 0x00080000 //524288
#define SOLDIER_LIGHT_OWNER 0x00010000 //65536 // we 'own' at least one light source (via flashlights)
#define SOLDIER_AIRDROP_BONUS 0x00020000 //131072 // backgrounds: special AP bonus during the first turn of an airdrop
#define SOLDIER_ASSAULT_BONUS 0x00040000 //262144 // backgrounds: our first turn in an assault
#define SOLDIER_RADIO_OPERATOR_LISTENING 0x00080000 //524288 // radio operator is listening with his set
#define PLAYER_NET_1_LVL_2 0x00100000 //1048576
#define PLAYER_NET_2_LVL_2 0x00200000 //2097152
#define PLAYER_NET_3_LVL_2 0x00400000 //4194304
#define SOLDIER_RADIO_OPERATOR_JAMMING 0x00100000 //1048576 // radio operator is jamming frequencies
#define SOLDIER_RADIO_OPERATOR_SCANNING 0x00200000 //2097152 // radio operator is scanning for jammers
/*#define PLAYER_NET_3_LVL_2 0x00400000 //4194304
#define PLAYER_NET_4_LVL_2 0x00800000 //8388608
#define PLAYER_NET_1_LVL_3 0x01000000 //16777216
@@ -423,6 +423,36 @@ enum
NUM_MTA,
};
//Flugente skills from traits and other sources
enum{
// psyker skills
SKILLS_FIRST = 0,
// radio operator
SKILLS_RADIO_FIRST = SKILLS_FIRST,
SKILLS_RADIO_ARTILLERY = SKILLS_RADIO_FIRST,
SKILLS_RADIO_JAM,
SKILLS_RADIO_SCAN_FOR_JAM,
SKILLS_RADIO_LISTEN,
SKILLS_RADIO_CALLREINFORCEMENTS,
SKILLS_RADIO_TURNOFF,
SKILLS_RADIO_LAST = SKILLS_RADIO_TURNOFF,
SKILLS_MAX,
};
// Flugente: certain skills/traits/taints add effects that require a counter, here are enums for these
enum {
SOLDIER_COUNTER_RADIO_ARTILLERY, // there is actually no need for an artillery timer, but we use one to forbid the same AI guy ordering multiple strikes at once
SOLDIER_COUNTER_MAX = 20, // enough space for fillers
};
// Flugente: certain skills/traits/taints require a cooldown timer
enum {
SOLDIER_COOLDOWN_MAX = 20, // enough space for fillers
};
// enum of uniform pieces
typedef struct
{
@@ -1297,12 +1327,17 @@ public:
UINT16 usSoldierProfile; // Flugente: allow linking to a xml-based profile specifiying name, visuals, traits etc.
// Flugente: sector ID for move items assignemnt
// Flugente: sector ID for move items assignment
UINT8 usItemMoveSectorID;
// Flugente: skill stuff
UINT8 usAISkillUse; // this variable allows the AI to remember which skill it wants to use
UINT16 usSkillCounter[SOLDIER_COUNTER_MAX]; // counters used for various skill/trait/taint effects
UINT32 usSkillCooldown[SOLDIER_COOLDOWN_MAX]; // cooldown used for various skill/trait/taint effects
// Flugente: Decrease this filler by 1 for each new UINT8 / BOOLEAN variable, so we can maintain savegame compatibility!!
// Note that we also have to account for padding, so you might need to substract more than just the size of the new variables
UINT8 ubFiller[7];
UINT8 ubFiller[20];
#ifdef JA2UB
//ja25
@@ -1610,6 +1645,38 @@ public:
void SoldierPropertyUpkeep(); // update functions for various properties (updating counters, resetting flags etc.)
// Flugente: functions for skill usage
// traits can allow use of certain skills
// check if Soldier can use the spell skillwise, with fAPCheck = TRUE also check current APs
BOOLEAN CanUseSkill( INT8 iSkill, BOOLEAN fAPCheck = TRUE );
// use a skill. For safety reasons, this calls CanUseSkill again (it is possible to switch the soldier while the menu is open)
BOOLEAN UseSkill( UINT8 iSkill, INT32 usMapPos, UINT8 ID );
// is the AI allowed to use a skill? we have to check how much breath and life using this skill would cost, as otherwise the AI might commit suicide by casting
BOOLEAN IsAIAllowedtoUseSkill( INT8 iSkill );
// print a small description of the skill if we can use it, or its requirements if we cannot
STR16 PrintSkillDesc( INT8 iSkill);
// Flugente: functions for the radio operator trait
BOOLEAN CanUseRadio(); // can we use radio, if we even have one?
BOOLEAN UseRadio(); // simply drain the batteries
BOOLEAN HasMortar();
BOOLEAN GetSlotOfSignalShellIfMortar(UINT8* pbLoop); // if we have a mortar and a fitting signal shell, return the inventory slot it is in
BOOLEAN CanAnyArtilleryStrikeBeOrdered(UINT32* pSectorID); // can any artillery strikes be ordered by this guy's team from the neighbouring sectors?
BOOLEAN OrderArtilleryStrike( UINT32 usSectorNr, INT32 sTargetGridNo, UINT8 bTeam );
BOOLEAN IsJamming(); // are we currently jamming communication frequencies?
BOOLEAN JamCommunications();
BOOLEAN IsScanning();
BOOLEAN ScanForJam();
BOOLEAN IsRadioListening();
BOOLEAN RadioListen();
BOOLEAN RadioCallReinforcements( UINT32 usSector, UINT16 sNumber );
BOOLEAN SwitchOffRadio();
void RadioFail(); // display and error sound used either when the radio set fails or the sector is jammed - the player knows of the error, but cannot be sure of the cause
void DepleteActiveRadioSetEnergy(BOOLEAN fActivation = FALSE, BOOLEAN fAssignment = FALSE);
//////////////////////////////////////////////////////////////////////////////
}; // SOLDIERTYPE;
@@ -1737,7 +1804,12 @@ BOOLEAN ResolvePendingInterrupt( SOLDIERTYPE * pSoldier, UINT8 ubInterruptType )
BOOLEAN AIDecideHipOrShoulderStance( SOLDIERTYPE * pSoldier, INT32 iGridNo );
BOOLEAN DecideAltAnimForBigMerc( SOLDIERTYPE * pSoldier );
BOOLEAN TwoStagedTrait( UINT8 uiSkillTraitNumber ); // Flugente: determine if this (new) trait has two stages
// added by Flugente
BOOLEAN TwoStagedTrait( UINT8 uiSkillTraitNumber ); // determine if this (new) trait has two stages
BOOLEAN GetRadioOperatorSignal(UINT8 usOwner, INT32* psTargetGridNo); // retrieve the gridno of a radio operator who (or whose team) ordered an artillery strike
BOOLEAN IsValidArtilleryOrderSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 bTeam ); // can an artillery strike be ordered FROM this sector
BOOLEAN SectorJammed();
BOOLEAN PlayerTeamIsScanning();
//typedef struct
class OLDSOLDIERTYPE_101
+28
View File
@@ -4630,6 +4630,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
BOOLEAN foundThrowing = FALSE;
BOOLEAN foundHtH = FALSE;
BOOLEAN foundMelee = FALSE;
BOOLEAN fRadioSetFound = FALSE;
// FIRST FIND OUT THE COMPOSITION OF OUR GEAR
for (bLoop = 0; bLoop < (INT8) pSoldier->inv.size(); bLoop++)
@@ -4653,6 +4654,8 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
else if (Item[pCreateStruct->Inv[bLoop].usItem].usItemClass == 128 && // 128 is an identifier of blunt melee weapons
Item[pCreateStruct->Inv[bLoop].usItem].uiIndex != 0 )
foundMelee = TRUE;
else if ( HasItemFlag(pCreateStruct->Inv[bLoop].usItem, RADIO_SET) )
fRadioSetFound = TRUE;
}
}
@@ -5191,6 +5194,31 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
}
}
}
// Flugente: new traits
if ( gGameOptions.fNewTraitSystem && (!ATraitAssigned || !BTraitAssigned || !CTraitAssigned ) )
{
// if we have a radio set, give us the corresponding trait so we can use it...
if ( fRadioSetFound )
{
if ( !ATraitAssigned )
{
pSoldier->stats.ubSkillTraits[0] = RADIO_OPERATOR_NT;
ATraitAssigned = TRUE;
}
else if ( !BTraitAssigned )
{
pSoldier->stats.ubSkillTraits[1] = RADIO_OPERATOR_NT;
BTraitAssigned = TRUE;
}
else if ( ubSolClass == SOLDIER_CLASS_ELITE || ubSolClass == SOLDIER_CLASS_ELITE_MILITIA )
{
pSoldier->stats.ubSkillTraits[2] = RADIO_OPERATOR_NT;
CTraitAssigned = TRUE;
return( TRUE ); // We no longer need to continue from here
}
}
}
}
// RETURN TRUE IF ALL TRAITS ASSIGNED OTHERWISE FALSE
if (( !gGameOptions.fNewTraitSystem && ATraitAssigned && BTraitAssigned ) || ( gGameOptions.fNewTraitSystem && ATraitAssigned && BTraitAssigned && CTraitAssigned ) )
+8
View File
@@ -578,6 +578,10 @@
RelativePath=".\SkillCheck.h"
>
</File>
<File
RelativePath=".\SkillMenu.h"
>
</File>
<File
RelativePath=".\Soldier Add.h"
>
@@ -904,6 +908,10 @@
RelativePath=".\SkillCheck.cpp"
>
</File>
<File
RelativePath=".\SkillMenu.cpp"
>
</File>
<File
RelativePath=".\Soldier Add.cpp"
>
+8
View File
@@ -582,6 +582,10 @@
RelativePath="SkillCheck.h"
>
</File>
<File
RelativePath="SkillMenu.h"
>
</File>
<File
RelativePath="Soldier Add.h"
>
@@ -906,6 +910,10 @@
RelativePath="SkillCheck.cpp"
>
</File>
<File
RelativePath="SkillMenu.cpp"
>
</File>
<File
RelativePath="Soldier Add.cpp"
>
+2
View File
@@ -83,6 +83,7 @@
<ClInclude Include="ShopKeeper Interface.h" />
<ClInclude Include="ShopKeeper Quotes.h" />
<ClInclude Include="SkillCheck.h" />
<ClInclude Include="SkillMenu.h" />
<ClInclude Include="Soldier Add.h" />
<ClInclude Include="Soldier Ani.h" />
<ClInclude Include="Soldier Control.h" />
@@ -165,6 +166,7 @@
<ClCompile Include="Rotting Corpses.cpp" />
<ClCompile Include="ShopKeeper Interface.cpp" />
<ClCompile Include="SkillCheck.cpp" />
<ClCompile Include="SkillMenu.cpp" />
<ClCompile Include="Soldier Add.cpp" />
<ClCompile Include="Soldier Ani.cpp" />
<ClCompile Include="Soldier Control.cpp" />
+6
View File
@@ -264,6 +264,9 @@
<ClInclude Include="Food.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SkillMenu.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Air Raid.cpp">
@@ -647,5 +650,8 @@
<ClCompile Include="XML_Background.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SkillMenu.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
+11 -2
View File
@@ -114,7 +114,8 @@
#include "fresh_header.h"
#include "IMP Skill Trait.h" // added by Flugente
#include "IMP Skill Trait.h" // added by Flugente
#include "SkillMenu.h" // added by Flugente
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
@@ -2495,7 +2496,15 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
break;
case '$':
ChangeCurrentSquad( 13 );
{
// Flugente: trait skill selection menu. Yes, screw squad 13
INT32 usMapPos;
if ( GetMouseMapPos( &usMapPos ) )
{
TraitsMenu(usMapPos);
}
}
//ChangeCurrentSquad( 13 );
break;
case '%':
+81
View File
@@ -13019,4 +13019,85 @@ FLOAT CalcNewChanceToHitAimTraitBonus(SOLDIERTYPE *pSoldier, FLOAT fAimCap, FLOA
}
return fAimChance;
}
extern BOOLEAN IsRoofPresentAtGridNo( INT32 sGridNo );
// Flugente: fire item from A to B (intended for mortarshells and launchable grenades)
BOOLEAN ArtilleryStrike( UINT16 usItem, UINT32 usStartingGridNo, UINT32 usTargetMapPos )
{
FLOAT dForce, dDegrees;
INT16 sDestX, sDestY, sSrcX, sSrcY;
vector_3 vForce, vDirNormal;
INT16 sStartZ = ( 1 * 256 ) + 50;
INT16 sEndZ = 0;
// radius is way smaller for signal shells, otherwise the inaccuraccy would increase too much
INT8 bRadius = gSkillTraitValues.usVOMortarRadius;
if ( HasItemFlag(usItem, SIGNAL_SHELL) )
bRadius = gSkillTraitValues.usVOMortarSignalShellRadius;
INT32 sTargetGridNo = GetArtilleryTargetGridNo( usTargetMapPos, bRadius );
if ( TileIsOutOfBounds(sTargetGridNo) )
return FALSE;
UINT8 ubLevel = 0;
if ( IsRoofPresentAtGridNo( sTargetGridNo ) )
ubLevel = 1;
// create shell
OBJECTTYPE shellobj;
CreateItem( usItem, 100, &shellobj );
// Get basic launch params...
if ( !GetArtilleryLaunchParams(usStartingGridNo, sTargetGridNo, sStartZ, sEndZ, usItem, &shellobj, &dForce, &dDegrees) )
return FALSE;
// Get XY from gridno
ConvertGridNoToCenterCellXY( sTargetGridNo, &sDestX, &sDestY );
ConvertGridNoToCenterCellXY( usStartingGridNo, &sSrcX, &sSrcY );
// OK, get direction normal
vDirNormal.x = (float)(sDestX - sSrcX);
vDirNormal.y = (float)(sDestY - sSrcY);
vDirNormal.z = 0;
// NOmralize
vDirNormal = VGetNormal( &vDirNormal );
// From degrees, calculate Z portion of normal
vDirNormal.z = (float)sin( dDegrees );
// Do force....
vForce.x = dForce * vDirNormal.x;
vForce.y = dForce * vDirNormal.y;
vForce.z = dForce * vDirNormal.z;
float dX = (float)sSrcX;
float dY = (float)sSrcY;
float dZ = (float)sStartZ;
float dForceX = vForce.x;
float dForceY = vForce.y;
float dForceZ = vForce.z;
if ( Weapon[ usItem ].sSound != NO_WEAPON_SOUND )
{
PlayJA2Sample( Weapon[ usItem ].sSound, RATE_11025, SoundVolume( HIGHVOLUME, usStartingGridNo ), 1, SoundDir( usStartingGridNo ) );
}
INT32 iID = CreatePhysicalObject( &shellobj, -1, dX, dY, dZ, dForceX, dForceY, dForceZ, 0, THROW_ARM_ITEM, 0, FALSE );
// OJW - 20091002 - Explosives
/*if (is_networked && is_client)
{
if (pSoldier->bTeam == 0 || (pSoldier->bTeam == 1 && is_server))
{
send_grenade( &shellobj , dLifeSpan,dX, dY, dZ, dForceX, dForceY, dForceZ, sTargetGridNo, pSoldier->ubID, ubActionCode, uiActionData, iID , false);
}
}*/
//REAL_OBJECT* pObject = &( ObjectSlots[ iID ] );
return TRUE;
}
+3
View File
@@ -283,6 +283,7 @@ enum
EXPLOSV_CREATUREGAS,
EXPLOSV_BURNABLEGAS,
EXPLOSV_FLASHBANG,
EXPLOSV_SIGNAL_SMOKE,
};
#define AMMO_DAMAGE_ADJUSTMENT_BUCKSHOT( x ) (x / 4)
@@ -539,4 +540,6 @@ FLOAT GetOverheatJamThreshold( OBJECTTYPE *pObj );
FLOAT GetOverheatDamageThresholdModifier( OBJECTTYPE *pObj );
FLOAT GetOverheatDamageThreshold( OBJECTTYPE *pObj );
BOOLEAN ArtilleryStrike( UINT16 usItem, UINT32 usStartingGridNo, UINT32 usTargetMapPos );
#endif
+3
View File
@@ -136,6 +136,9 @@ explosiveEndElementHandle(void *userData, const XML_Char *name)
{
pData->curElement = ELEMENT;
pData->curExplosive.ubRadius = (UINT8) atol(pData->szCharData);
// Flugente: variable is UINT16, but is always used as UINT8, so better keep it in line
pData->curExplosive.ubRadius = max( 0, min(255, pData->curExplosive.ubRadius));
}
else if(strcmp(name, "ubVolume") == 0)
{
+4 -3
View File
@@ -161,19 +161,20 @@ typedef enum
// Flugente: new traits have to go here, even if they are major traits, as otherwise the existing traits in profiles get mixed up
COVERT_NT, // 20
RADIO_OPERATOR_NT, //21 // a minor trait
NUM_SKILLTRAITS_NT
} SkillTraitNew;
#define NUM_MAJOR_TRAITS 10
#define NUM_MINOR_TRAITS 10
#define NUM_MINOR_TRAITS 11
#define NUM_ORIGINAL_MAJOR_TRAITS 9
// Flugente: I've had it with this hardcoding madness. Without this, adding or removing a new trait would crash anything related to a bubblehelp display of traits
// always check every use of these enums and every use of the skill-strings if you add a new trait
#define NEWTRAIT_MERCSKILL_EXPERTOFFSET NUM_MAJOR_TRAITS + NUM_MINOR_TRAITS
#define NEWTRAIT_MERCSKILL_OFFSET_ALL NEWTRAIT_MERCSKILL_EXPERTOFFSET + NUM_MAJOR_TRAITS
#define NEWTRAIT_MERCSKILL_EXPERTOFFSET (NUM_MAJOR_TRAITS + NUM_MINOR_TRAITS)
#define NEWTRAIT_MERCSKILL_OFFSET_ALL (NEWTRAIT_MERCSKILL_EXPERTOFFSET + NUM_MAJOR_TRAITS)
// SANDRO - new set of character traits
typedef enum