mirror of
https://github.com/1dot13/source.git
synced 2026-08-12 14:10:23 +02:00
HAM5.5b2 merged in!
Notes: -There may still be bugs!! (In fact, I almost guarantee it -- there's -Ammo box code added to HR's crate code -Splitting a crate/box also automatically refills half empty magazines -new pathing arrows for map screen not included -code for scouts to know where enemies are going doesn't appear to work... but i'm not sure it was completed. -lots of gobledy gook (chinese?) comments turned back to english -also added Bob's popups -other languages besides english still need to have there language.cpp files updated with array changes -AI enhancements by Warmsteel (reloading, suppression, roaming, avoiding gas, and other fixes) git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5181 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -50,17 +50,17 @@ static UINT16 CrouchedShootRocketScript[MAX_FRAMES_PER_ANIM] =
|
||||
{757,1,2,3,4,5,6,7,8,9,10,11,12,470,430,13,14,15,16,477,17,18,19,20,753,499,999,0,0,0,0};
|
||||
static UINT16 SwatWithKnifeScript[MAX_FRAMES_PER_ANIM] =
|
||||
//{1,2,3,4,5,6,7,703,8,9,10,11,704,12,13,14,15,16,17,18,19,501,999,0,0,0,0};
|
||||
{5,703,6,7,8,9,10,11,704,12,13,14,15,16,501,999,0,0,0,0};//òàêàÿ ïîñëåäîâàòåëüíîñòü ïðåäëàãàåòñÿ â äæà2áèí
|
||||
{5,703,6,7,8,9,10,11,704,12,13,14,15,16,501,999,0,0,0,0};//such a sequence is available in dzha2bin
|
||||
static UINT16 SwatBackWithKnifeScript[MAX_FRAMES_PER_ANIM] =
|
||||
{16,15,14,13,12,704,11,10,9,8,7,6,703,5,501,999,0,0,0,0};
|
||||
|
||||
static UINT16 SwatBackWithNothingScript[MAX_FRAMES_PER_ANIM] =
|
||||
{16,15,14,13,12,704,11,10,9,8,7,6,703,5,501,999,0,0,0,0};
|
||||
|
||||
//õç, ìîæåò ïîíàäîáèòñÿ ïðàâèòü öèôðû. ñêðèïò êèäàíèÿ ãðàíàò
|
||||
//xs, may need to edit the numbers. throwing grenades script
|
||||
static UINT16 ThrowGrenadeStanceAnimationScript[MAX_FRAMES_PER_ANIM] = { 1,2,3,4,5,6,7,8,9,10,460,11,12,13,14,15,16,17,18,19,442,601,999,0,0,0,0 };
|
||||
static UINT16 LobGrenadeStanceAnimationScript[MAX_FRAMES_PER_ANIM] = { 1,2,3,4,5,6,7,8,9,10,460,11,12,13,14,15,16,17,18,19,442,601,999,0,0,0,0 };
|
||||
//ïåðåêàò
|
||||
//Rolls
|
||||
static UINT16 ROLL_L_AnimationScript[MAX_FRAMES_PER_ANIM] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,501,999,0,0,0,0 };
|
||||
static UINT16 ROLL_R_AnimationScript[MAX_FRAMES_PER_ANIM] = { 14,13,12,11,10,9,8,7,6,5,4,3,2,1,501,999,0,0,0,0 };
|
||||
|
||||
@@ -1781,10 +1781,10 @@ void InitAnimationSurfacesPerBodytype( )
|
||||
gubAnimSurfaceIndex[ BIGMALE ][ SWATTING_WK ] = BGMSWKNIFE;
|
||||
gubAnimSurfaceIndex[ BIGMALE ][ SWAT_BACKWARDS_WK ] = BGMSWKNIFE;
|
||||
gubAnimSurfaceIndex[ BIGMALE ][ SWAT_BACKWARDS_NOTHING ] = BGMNOTHING_SWAT;
|
||||
//êèäàíèå ãðàíàòû
|
||||
//Throwing Grenades
|
||||
gubAnimSurfaceIndex[ BIGMALE ][ THROW_GRENADE_STANCE ] = BGMSTHRG;
|
||||
gubAnimSurfaceIndex[ BIGMALE ][ LOB_GRENADE_STANCE ] = BGMSLOBG;
|
||||
//ïåðåêàò
|
||||
//Rolling
|
||||
gubAnimSurfaceIndex[ BIGMALE ][ ROLL_PRONE_L ] = BGMROLL_PR;
|
||||
gubAnimSurfaceIndex[ BIGMALE ][ ROLL_PRONE_R ] = BGMROLL_PR;
|
||||
|
||||
@@ -2182,10 +2182,10 @@ void InitAnimationSurfacesPerBodytype( )
|
||||
gubAnimSurfaceIndex[ STOCKYMALE ][ SWATTING_WK ] = RGMSWKNIFE;
|
||||
gubAnimSurfaceIndex[ STOCKYMALE ][ SWAT_BACKWARDS_WK ] = RGMSWKNIFE;
|
||||
gubAnimSurfaceIndex[ STOCKYMALE ][ SWAT_BACKWARDS_NOTHING ] = RGMNOTHING_SWAT;
|
||||
//êèäàíèå ãðàíàòû
|
||||
//Throwing Grenades
|
||||
gubAnimSurfaceIndex[ STOCKYMALE ][ THROW_GRENADE_STANCE ] = RGMSTHRG;
|
||||
gubAnimSurfaceIndex[ STOCKYMALE ][ LOB_GRENADE_STANCE ] = RGMSLOBG;
|
||||
//ïåðåêàò
|
||||
//Rolling
|
||||
gubAnimSurfaceIndex[ STOCKYMALE ][ ROLL_PRONE_L ] = RGMROLL_PR;
|
||||
gubAnimSurfaceIndex[ STOCKYMALE ][ ROLL_PRONE_R ] = RGMROLL_PR;
|
||||
|
||||
@@ -2562,10 +2562,10 @@ void InitAnimationSurfacesPerBodytype( )
|
||||
gubAnimSurfaceIndex[ REGFEMALE ][ SWAT_BACKWARDS_NOTHING ] = RGFNOTHING_SWAT;
|
||||
gubAnimSurfaceIndex[ REGFEMALE ][ SWATTING_WK ] = RGFSWKNIFE;
|
||||
gubAnimSurfaceIndex[ REGFEMALE ][ SWAT_BACKWARDS_WK ] = RGFSWKNIFE;
|
||||
//êèäàíèå ãðàíàòû
|
||||
//Throwing Grenades
|
||||
gubAnimSurfaceIndex[ REGFEMALE ][ THROW_GRENADE_STANCE ] = RGFSTHRG;
|
||||
gubAnimSurfaceIndex[ REGFEMALE ][ LOB_GRENADE_STANCE ] = RGFSLOBG;
|
||||
//ïåðåêòà
|
||||
//Rolling
|
||||
gubAnimSurfaceIndex[ REGFEMALE ][ ROLL_PRONE_L ] = RGFROLL_PR;
|
||||
gubAnimSurfaceIndex[ REGFEMALE ][ ROLL_PRONE_R ] = RGFROLL_PR;
|
||||
|
||||
@@ -3247,8 +3247,7 @@ BOOLEAN LoadAnimationStateInstructions( )
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
//ddd ïàòàìóøòà âûëåòàåò ïðè ïðåâûøåíèè 320 çíà÷åíèÿ ;(
|
||||
//ïðèäåòñÿ ìàñòåðèòü âñïîìîãàòåëüíûé ìàññèâ, ïîòîì êîïèðîâàòü åãî ñîäåðæèìîå â ãóñàíèìèíñò
|
||||
//ddd Trick for loading more than 320 animation files (?)
|
||||
UINT16 fuckTheBoundz[320][100];
|
||||
|
||||
//Read in block
|
||||
@@ -3265,7 +3264,7 @@ BOOLEAN LoadAnimationStateInstructions( )
|
||||
memcpy(gusAnimInst[i],fuckTheBoundz[i],sizeof(fuckTheBoundz[i]));
|
||||
//gusAnimInst[i][0] = fuckTheBoundz[i][0];
|
||||
|
||||
//! äëÿ ïåðåãîíêè äæà2áèí â ÷èòàåìûé âèä
|
||||
// For conversion into readable format (?)
|
||||
// char gS[22];
|
||||
// UINT32 uiNumBytesWritten = 64000;
|
||||
// int ggg[MAX_ANIMATIONS][MAX_FRAMES_PER_ANIM];
|
||||
@@ -3837,7 +3836,7 @@ UINT16 DetermineSoldierAnimationSurface( SOLDIERTYPE *pSoldier, UINT16 usAnimSta
|
||||
|
||||
if ( usAltAnimSurface != INVALID_ANIMATION )
|
||||
{
|
||||
//ddd{ ñþäà ñòàâèòü àëüòåðíàòèâíóþ àíèìàøêó äëÿ âûñòðåëà èç ïèñòîëåòà
|
||||
//ddd Put alternative pistol-shot animations here
|
||||
/*if ( usAnimSurface == BGMSTANDAIM2 )
|
||||
{
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
// Defines
|
||||
// #######################################################
|
||||
#define MAX_ANIMATIONS 350 //!!!!!ddd ïîêà äîáàâèë 30 ëèøíèõ ñëîâòîâ ïîä àíèìàøêè.
|
||||
#define MAX_ANIMATIONS 350 //!!!!!ddd added 30 new animations
|
||||
#define MAX_FRAMES_PER_ANIM 100
|
||||
#define MAX_RANDOM_ANIMS_PER_BODYTYPE 8
|
||||
|
||||
@@ -548,9 +548,9 @@ enum AnimationStates
|
||||
SWATTING_WK,
|
||||
SWAT_BACKWARDS_WK,
|
||||
SWAT_BACKWARDS_NOTHING,
|
||||
THROW_GRENADE_STANCE, //ddd äëÿ áàáû àíèìàöèè íåò - èñïîëüçóåì ñòàíäàðòíóþ
|
||||
THROW_GRENADE_STANCE, //ddd Currently no animation for women. Using the standard.
|
||||
LOB_GRENADE_STANCE,
|
||||
//ïåðåêàòòû
|
||||
//Prone rolls
|
||||
ROLL_PRONE_R,
|
||||
ROLL_PRONE_L,
|
||||
|
||||
|
||||
@@ -518,15 +518,15 @@ BGMWITHSTONE,
|
||||
BGMSWKNIFE,
|
||||
RGFSWKNIFE,
|
||||
RGMSWKNIFE,
|
||||
//êèäàíèå ãðàíàòû ñòîÿ ñ âûä. ÷åêè
|
||||
//Launch grenade (?)
|
||||
BGMSTHRG,
|
||||
RGFSTHRG,
|
||||
RGMSTHRG,
|
||||
//êèäàíèå ãðàíàòû ñòîÿ ñ âûä. ÷åêè áëèçêîå ðàññò
|
||||
//Lob grenade
|
||||
BGMSLOBG,
|
||||
RGFSLOBG,
|
||||
RGMSLOBG,
|
||||
//âíàãëóþ ñòûðèë êîä ó òåðàïåâòà!
|
||||
//Roll while prone
|
||||
RGMROLL_PR,
|
||||
BGMROLL_PR,
|
||||
RGFROLL_PR,
|
||||
|
||||
@@ -57,6 +57,7 @@ typedef struct
|
||||
UINT8 ubTilesPerUpdate;
|
||||
UINT16 usClockTicksPerUpdate;
|
||||
SOLDIERTYPE *pFirer;
|
||||
INT32 sOrigGridNo; // HEADROCK HAM 5.1: Original tile does not necessarily have to be the pFirer's tile
|
||||
INT32 sTargetGridNo;
|
||||
INT16 sHitBy;
|
||||
INT32 iImpact;
|
||||
@@ -73,6 +74,8 @@ typedef struct
|
||||
// the bullet animation functions to create a lightpath for this bullet. This means now all bullets in a tracer
|
||||
// magazine will cause a lightshow (that's the intended result).
|
||||
BOOLEAN fTracer;
|
||||
// HEADROCK HAM 5: Fragments. They are handled slightly differently by the bullet functions.
|
||||
BOOLEAN fFragment;
|
||||
} BULLET;
|
||||
|
||||
extern UINT32 guiNumBullets;
|
||||
@@ -82,6 +85,8 @@ void RemoveBullet( INT32 iBullet );
|
||||
void StopBullet( INT32 iBullet );
|
||||
void UpdateBullets( );
|
||||
BULLET *GetBulletPtr( INT32 iBullet );
|
||||
INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 iImpact, INT16 sHitBy, UINT8 * pubSpecial );
|
||||
|
||||
|
||||
void DeleteAllBullets( );
|
||||
|
||||
|
||||
+1047
-400
File diff suppressed because it is too large
Load Diff
+1984
-6
File diff suppressed because it is too large
Load Diff
@@ -169,6 +169,19 @@ public:
|
||||
OBJECTTYPE ItemPointerInfo;
|
||||
};
|
||||
|
||||
// HEADROCK HAM 5: Enums for big-item display attachment asterisks.
|
||||
enum
|
||||
{
|
||||
ATTACHMENT_NONE,
|
||||
ATTACHMENT_GENERAL,
|
||||
ATTACHMENT_GL,
|
||||
ATTACHMENT_RECOILREDUCTION,
|
||||
ATTACHMENT_OPTICAL,
|
||||
};
|
||||
|
||||
// HEADROCK HAM 5: Asterisks for use with big item images
|
||||
extern UINT32 guiAttachmentAsterisks;
|
||||
|
||||
// Itempickup stuff
|
||||
BOOLEAN InitializeItemPickupMenu( SOLDIERTYPE *pSoldier, INT32 sGridNo, ITEM_POOL *pItemPool, INT16 sScreenX, INT16 sScreenY, INT8 bZLevel );
|
||||
void RenderItemPickupMenu( );
|
||||
@@ -211,6 +224,8 @@ BOOLEAN HandleCompatibleAmmoUI( SOLDIERTYPE *pSoldier, INT8 bInvPos, BOOLEAN fOn
|
||||
|
||||
void RenderBulletIcon(OBJECTTYPE *pObject, UINT32 ubStatusIndex = 0);
|
||||
void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObject, INT16 sX, INT16 sY, INT16 sWidth, INT16 sHeight, UINT8 fDirtyLevel, UINT8 *pubHighlightCounter, UINT8 ubStatusIndex, BOOLEAN fOutline, INT16 sOutlineColor, UINT8 iter = 0 );
|
||||
// HEADROCK HAM 5: Drawing a large item pic with extra data.
|
||||
void MAPINVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObject, UINT32 uiItemGraphicNum, INT16 sX, INT16 sY, INT16 sWidth, INT16 sHeight, BOOLEAN fOutline, INT16 sOutlineColor );
|
||||
// CHRISL: Add a new function that will be used to render a pocket silhouette
|
||||
void INVRenderSilhouette( UINT32 uiBugger, INT16 PocketIndex, INT16 SilIndex, INT16 sX, INT16 sY, INT16 sWideth, INT16 sHeight);
|
||||
// CHRISL: New function to handle display of inventory quantities based on item current in cursor
|
||||
@@ -313,7 +328,36 @@ extern INT32 giActiveAttachmentPopup; // the attachment popup to display in maps
|
||||
extern POPUP* gEquipPopups[NUM_INV_SLOTS]; // popup list for attachment slots
|
||||
extern INT32 giActiveEquipPopup; // the attachment popup to display in mapscreen
|
||||
|
||||
// HEADROCK HAM 5: Item Transformation Popup
|
||||
extern POPUP* gItemDescTransformPopup;
|
||||
extern BOOLEAN gfItemDescTransformPopupInitialized;
|
||||
extern BOOLEAN gfItemDescTransformPopupVisible;
|
||||
|
||||
// BOB : duh...
|
||||
void DoAttachment( UINT8 subObject, INT32 iItemPos );
|
||||
|
||||
// THE_BOB (AKA BOB): ammo box/mag popups
|
||||
void PocketPopupFull( SOLDIERTYPE *pSoldier, INT16 sPocket ); // displays all suported options
|
||||
void PocketPopupDefault( SOLDIERTYPE *pSoldier, INT16 sPocket ); // displays only pocket-specific (predefined) options
|
||||
|
||||
POPUP * createPopupForPocket( SOLDIERTYPE *pSoldier, INT16 sPocket ); // creates a popup positioned next to the pocket
|
||||
|
||||
// THE_BOB
|
||||
extern UINT16 gsPocketUnderCursor;
|
||||
|
||||
|
||||
void addArmorToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addLBEToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addWeaponsToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addWeaponGroupsToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addGrenadesToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addBombsToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addFaceGearToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addAmmoToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
|
||||
void addRifleGrenadesToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addRocketAmmoToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addMiscToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addKitsToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2531,7 +2531,15 @@ void RenderSMPanel( BOOLEAN *pfDirty )
|
||||
}
|
||||
}
|
||||
|
||||
RenderItemDescriptionBox( );
|
||||
// HEADROCK HAM 5: Test for active Transform Popup
|
||||
if (gfItemDescTransformPopupVisible)
|
||||
{
|
||||
gItemDescTransformPopup->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderItemDescriptionBox( );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -545,4 +545,16 @@ void RenderSoldierFace( SOLDIERTYPE *pSoldier, INT16 sFaceX, INT16 sFaceY, BOOLE
|
||||
|
||||
}
|
||||
|
||||
// HEADROCK HAM 5: This function draws a rectangle around the item image in the zoomed inventory
|
||||
void DrawItemOutlineZoomedInventory( INT16 sX, INT16 sY, INT16 sWidth, INT16 sHeight, INT16 sColor, UINT32 uiBuffer )
|
||||
{
|
||||
UINT32 uiDestPitchBYTES;
|
||||
UINT8 *pDestBuf;
|
||||
|
||||
pDestBuf = LockVideoSurface( uiBuffer, &uiDestPitchBYTES );
|
||||
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
|
||||
|
||||
RectangleDraw( TRUE, sX, sY, sWidth, sHeight, sColor, pDestBuf );
|
||||
|
||||
UnLockVideoSurface( uiBuffer );
|
||||
}
|
||||
|
||||
@@ -23,5 +23,8 @@ BOOLEAN LoadCarPortraitValues( void );
|
||||
// get rid of the loaded portraits for cars
|
||||
void UnLoadCarPortraits( void );
|
||||
|
||||
// HEADROCK HAM 5: Helper for zoomed inventory
|
||||
void DrawItemOutlineZoomedInventory( INT16 sX, INT16 sY, INT16 sWidth, INT16 sHeight, INT16 sColor, UINT32 uiBuffer );
|
||||
|
||||
|
||||
#endif
|
||||
@@ -128,6 +128,7 @@ void DestroyLBE(OBJECTTYPE* pObj)
|
||||
|
||||
void MoveItemsInSlotsToLBE( SOLDIERTYPE *pSoldier, std::vector<INT8>& LBESlots, LBENODE* pLBE, OBJECTTYPE* pObj)
|
||||
{
|
||||
|
||||
for(unsigned int i=0; i<LBESlots.size(); i++) // Go through default pockets one by one
|
||||
{
|
||||
if(pSoldier->inv[LBESlots[i]].exists() == false) // No item in this pocket
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
#include "types.h"
|
||||
#include <vector>
|
||||
#include <list>
|
||||
// THE_BOB : added for pocket popup definitions
|
||||
#include <map>
|
||||
#include "popup_definition.h"
|
||||
|
||||
//if the number of slots are ever changed, the loading / saving checksum should use this value to make conversion easier
|
||||
#define NUM_ORIGINAL_INV_SLOTS 19
|
||||
@@ -264,6 +267,20 @@ extern std::list<LBENODE> LBEArray;
|
||||
#define OLD_MAX_ATTACHMENTS_101 4
|
||||
#define OLD_MAX_OBJECTS_PER_SLOT_101 8
|
||||
|
||||
// HEADROCK HAM 5: Define Self-Transformations
|
||||
// Have to define this early on, because this struct is used in OBJECTTYPE
|
||||
#define MAX_NUM_TRANSFORMATION_RESULTS 10
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 usItem;
|
||||
UINT16 usResult[MAX_NUM_TRANSFORMATION_RESULTS];
|
||||
UINT16 usAPCost;
|
||||
INT32 iBPCost;
|
||||
CHAR16 szMenuRowText[50];
|
||||
CHAR16 szTooltipText[300];
|
||||
} TransformInfoStruct;
|
||||
|
||||
namespace Version101
|
||||
{
|
||||
//union was originally unnamed
|
||||
@@ -526,6 +543,8 @@ public:
|
||||
BOOLEAN AttachObjectOAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttachment, BOOLEAN playSound = TRUE, UINT8 subObject = 0);
|
||||
BOOLEAN AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttachment, BOOLEAN playSound = TRUE, UINT8 subObject = 0, INT32 iItemPos = -1, BOOLEAN fRemoveProhibited = TRUE, std::vector<UINT16> usAttachmentSlotIndexVector = std::vector<UINT16>());
|
||||
BOOLEAN RemoveAttachment( OBJECTTYPE* pAttachment, OBJECTTYPE * pNewObj = NULL, UINT8 subObject = 0, SOLDIERTYPE * pSoldier = NULL, BOOLEAN fForceInseperable = FALSE, BOOLEAN fRemoveProhibited = TRUE);
|
||||
// HEADROCK HAM 5: Object Transformation
|
||||
BOOLEAN TransformObject( SOLDIERTYPE * pSoldier, UINT8 ubStatusIndex, TransformInfoStruct * Transform, OBJECTTYPE *pParent );
|
||||
|
||||
//see comments in .cpp
|
||||
static void DeleteMe(OBJECTTYPE** ppObject);
|
||||
@@ -590,6 +609,17 @@ extern OBJECTTYPE gTempObject;
|
||||
#define IC_BOBBY_GUN ( IC_GUN | IC_LAUNCHER )
|
||||
#define IC_BOBBY_MISC ( IC_GRENADE | IC_BOMB | IC_MISC | IC_MEDKIT | IC_KIT | IC_BLADE | IC_THROWING_KNIFE | IC_PUNCH | IC_FACE | IC_LBEGEAR )
|
||||
|
||||
// HEADROCK HAM 5: Inventory Filter Types
|
||||
#define IC_MAPFILTER_GUN ( IC_GUN | IC_LAUNCHER )
|
||||
#define IC_MAPFILTER_AMMO ( IC_AMMO )
|
||||
#define IC_MAPFILTER_EXPLOSV ( IC_GRENADE | IC_BOMB )
|
||||
#define IC_MAPFILTER_MELEE ( IC_BLADE | IC_PUNCH | IC_THROWN | IC_THROWING_KNIFE )
|
||||
#define IC_MAPFILTER_KIT ( IC_KIT | IC_MEDKIT | IC_APPLIABLE )
|
||||
#define IC_MAPFILTER_LBE ( IC_LBEGEAR | IC_BELTCLIP )
|
||||
#define IC_MAPFILTER_ARMOR ( IC_ARMOUR | IC_FACE )
|
||||
#define IC_MAPFILTER_MISC ( IC_TENTACLES | IC_KEY | IC_MISC | IC_MONEY | IC_NONE )
|
||||
#define IC_MAPFILTER_ALL ( IC_MAPFILTER_GUN | IC_MAPFILTER_AMMO | IC_MAPFILTER_EXPLOSV | IC_MAPFILTER_MELEE | IC_MAPFILTER_KIT | IC_MAPFILTER_LBE | IC_MAPFILTER_ARMOR | IC_MAPFILTER_MISC )
|
||||
|
||||
// Chrisl: Define attachment classes
|
||||
#define AC_DEFAULT1 0x00000001 //1
|
||||
#define AC_BARREL 0x00000002 //2
|
||||
@@ -904,6 +934,10 @@ public:
|
||||
};
|
||||
#define SIZEOF_POCKETTYPE offsetof( POCKETTYPE, POD )
|
||||
extern std::vector<POCKETTYPE> LBEPocketType;
|
||||
|
||||
// THE_BOB : added for pocket popup definitions
|
||||
extern std::map<UINT8,popupDef> LBEPocketPopup;
|
||||
|
||||
typedef enum ePOCKET_TYPE
|
||||
{
|
||||
NO_POCKET_TYPE = 0,
|
||||
@@ -1445,6 +1479,9 @@ typedef struct
|
||||
UINT32 uiIndex;
|
||||
} ComboMergeInfoStruct;
|
||||
|
||||
// HEADROCK HAM 5: Defining this here because we need MAXITEMS. The struct is defined earlier.
|
||||
extern TransformInfoStruct Transform[MAXITEMS+1];
|
||||
|
||||
extern ComboMergeInfoStruct AttachmentComboMerge[MAXITEMS+1];
|
||||
BOOLEAN EXPLOSIVE_GUN(UINT16 x );
|
||||
|
||||
|
||||
+384
-19
@@ -55,6 +55,9 @@
|
||||
#include "debug control.h"
|
||||
|
||||
#include "math.h"
|
||||
// THE_BOB : added for pocket popup definitions
|
||||
#include <map>
|
||||
#include "popup_definition.h"
|
||||
#endif
|
||||
|
||||
#ifdef JA2UB
|
||||
@@ -72,9 +75,19 @@ class SOLDIERTYPE;
|
||||
void SetNewItem( SOLDIERTYPE *pSoldier, UINT8 ubInvPos, BOOLEAN fNewItem );
|
||||
|
||||
extern SOLDIERTYPE *gpItemDescSoldier;
|
||||
// HEADROCK HAM 5: We need access to these values for item transformation purposes
|
||||
extern BOOLEAN gfItemDescObjectIsAttachment;
|
||||
extern OBJECTTYPE *gpItemDescObject;
|
||||
extern OBJECTTYPE *gpItemDescPrevObject;
|
||||
extern OBJECTTYPE *gpItemDescOrigAttachmentObject;
|
||||
extern OBJECTTYPE gCloneItemDescObject;
|
||||
extern BOOLEAN fShowMapInventoryPool;
|
||||
extern UINT32 guiCurrentItemDescriptionScreen;
|
||||
extern BOOLEAN AutoPlaceObjectInInventoryStash( OBJECTTYPE *pItemPtr, INT32 sGridNo );
|
||||
// HEADROCK HAM 5: Also need these to trigger Map Inventory changes appropriately.
|
||||
extern BOOLEAN fMapInventoryZoom;
|
||||
// HEADROCK HAM 5: And this, for checking whether an item is in the pool.
|
||||
extern std::vector<WORLDITEM> pInventoryPoolList;
|
||||
|
||||
UINT16 OldWayOfCalculatingScopeBonus(SOLDIERTYPE *pSoldier);
|
||||
// weight units are 100g each
|
||||
@@ -1154,6 +1167,8 @@ ComboMergeInfoStruct AttachmentComboMerge[MAXITEMS+1];// =
|
||||
// {NOTHING, {NOTHING, NOTHING}, NOTHING },
|
||||
//};
|
||||
|
||||
// HEADROCK HAM 5: Item Transformations table, containing all possible Transformations.
|
||||
TransformInfoStruct Transform[MAXITEMS+1];
|
||||
|
||||
UINT16 IncompatibleAttachments[MAXATTACHMENTS][2];// =
|
||||
//{
|
||||
@@ -1223,6 +1238,9 @@ std::vector<LBETYPE> LoadBearingEquipment;
|
||||
std::vector<POCKETTYPE> LBEPocketType;
|
||||
//TODO make the indices of this a define, because I do not know what is a large pocket (I guess 3)
|
||||
|
||||
// THE_BOB : added for pocket popup definitions
|
||||
std::map<UINT8,popupDef> LBEPocketPopup;
|
||||
|
||||
//POCKETTYPE LBEPocketType[MAXITEMS+1]; //=
|
||||
//{
|
||||
// { /* Blank Entry */ 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
|
||||
@@ -4761,7 +4779,8 @@ BOOLEAN OBJECTTYPE::AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttac
|
||||
|
||||
//WarmSteel - Replaced this with one that also checks default attachments, otherwise you could not replace built-in bonuses with default inseperable attachments.
|
||||
//RemoveProhibitedAttachments(pSoldier, this, usResult);
|
||||
ReInitMergedItem(pSoldier, this, usOldItem);
|
||||
// HEADROCK HAM 5: Added argument for statusindex.
|
||||
ReInitMergedItem(pSoldier, this, usOldItem, 0);
|
||||
|
||||
//AutoPlaceObject( pAttachment );
|
||||
//ADB ubWeight has been removed, see comments in OBJECTTYPE
|
||||
@@ -4866,7 +4885,7 @@ BOOLEAN OBJECTTYPE::AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttac
|
||||
|
||||
//WarmSteel - Replaced this with one that also checks default attachments, otherwise you could not replace built-in bonuses with default inseperable attachments.
|
||||
//RemoveProhibitedAttachments(pSoldier, this, usResult);
|
||||
ReInitMergedItem(pSoldier, this, usOldItem);
|
||||
ReInitMergedItem(pSoldier, this, usOldItem, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -4923,7 +4942,8 @@ BOOLEAN OBJECTTYPE::AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttac
|
||||
|
||||
//WarmSteel - Replaced this with one that also checks default attachments, otherwise you could not replace built-in bonuses with default inseperable attachments.
|
||||
//RemoveProhibitedAttachments(pSoldier, this, usResult);
|
||||
ReInitMergedItem(pSoldier, this, usOldItem);
|
||||
// HEADROCK HAM 5: Added argument for statusindex.
|
||||
ReInitMergedItem(pSoldier, this, usOldItem, subObject);
|
||||
|
||||
if ( ubType != TREAT_ARMOUR )
|
||||
{
|
||||
@@ -5296,7 +5316,9 @@ void RemoveProhibitedAttachments(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16
|
||||
//WarmSteel - Needed for merges, because the new items don't get their new default attachments.
|
||||
//This does the same as RemoveProhibitedAttachments but is a bit more thorough at it.
|
||||
//This is at the risk that items move around if more than one slot is valid, but since this is used for "new" guns after merges, that's acceptable.
|
||||
void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem){
|
||||
// HEADROCK HAM 5: Added argument for statusindex.
|
||||
void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem, UINT8 ubStatusIndex)
|
||||
{
|
||||
|
||||
attachmentList tempAttachList;
|
||||
attachmentList tempSlotChangingAttachList;
|
||||
@@ -5304,18 +5326,18 @@ void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem)
|
||||
UINT8 slotCount;
|
||||
std::vector<UINT16> usAttachmentSlotIndexVector = GetItemSlots(pObj);
|
||||
|
||||
if( !(*pObj)[0]->attachments.empty() ){
|
||||
if( !(*pObj)[ubStatusIndex]->attachments.empty() ){
|
||||
//Have to take all attachments off, because of possible incompatibilities with the default attachments (can't NOT attach a default attachment because some stupid item already attached is incompatible with it).
|
||||
|
||||
//Delete all default inseperable attachments from the old gun.
|
||||
//This is safe UNLESS the inseparable default attachments is not the only attachment of the same kind on the gun.
|
||||
//I can't think of any reason why this would happen, and if it does the worst that can happen is your attachment disappearing.
|
||||
for(slotCount = 0; slotCount < (*pObj)[0]->attachments.size(); slotCount++){
|
||||
UINT16 usAttach = (*pObj)[0]->GetAttachmentAtIndex(slotCount)->usItem;
|
||||
for(slotCount = 0; slotCount < (*pObj)[ubStatusIndex]->attachments.size(); slotCount++){
|
||||
UINT16 usAttach = (*pObj)[ubStatusIndex]->GetAttachmentAtIndex(slotCount)->usItem;
|
||||
if(Item[usAttach].inseparable){
|
||||
for(UINT16 cnt = 0; cnt < MAX_DEFAULT_ATTACHMENTS && Item[usOldItem].defaultattachments[cnt] != 0; cnt++){
|
||||
if(Item[usOldItem].defaultattachments[cnt] == usAttach){
|
||||
(*pObj)[0]->RemoveAttachmentAtIndex(slotCount);
|
||||
(*pObj)[ubStatusIndex]->RemoveAttachmentAtIndex(slotCount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -5323,36 +5345,38 @@ void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem)
|
||||
}
|
||||
slotCount = 0;
|
||||
//Put all other attachments into a temporary storage, so we can try to re-attach later.
|
||||
for(attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); iter++, slotCount++) {
|
||||
for(attachmentList::iterator iter = (*pObj)[ubStatusIndex]->attachments.begin(); iter != (*pObj)[ubStatusIndex]->attachments.end(); iter++, slotCount++) {
|
||||
if(iter->exists()){
|
||||
UINT16 cnt = 0;
|
||||
tempAttachList.push_back((*iter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//clear the attachment list, we've saved the attachments somewhere safe now.
|
||||
(*pObj)[0]->attachments.clear();
|
||||
(*pObj)[ubStatusIndex]->attachments.clear();
|
||||
|
||||
//Make sure the attachment slot data is correct.
|
||||
//std::vector<UINT16> tempItemSlots = GetItemSlots(pObj);
|
||||
(*pObj)[0]->attachments.resize(usAttachmentSlotIndexVector.size());
|
||||
(*pObj)[ubStatusIndex]->attachments.resize(usAttachmentSlotIndexVector.size());
|
||||
//pObj->usAttachmentSlotIndexVector = tempItemSlots;
|
||||
|
||||
|
||||
//Now add all default attachments, but add them with the same status as the gun. We don't want to make repairing guns easy :)
|
||||
for(UINT16 cnt = 0; cnt < MAX_DEFAULT_ATTACHMENTS && Item[pObj->usItem].defaultattachments[cnt] != 0; cnt++){
|
||||
//Only add inseparable default attachments, because they are likely "part" of the gun.
|
||||
if(Item[Item[pObj->usItem].defaultattachments[cnt]].inseparable){
|
||||
static OBJECTTYPE defaultAttachment;
|
||||
CreateItem(Item [ pObj->usItem ].defaultattachments[cnt],(*pObj)[0]->data.objectStatus,&defaultAttachment);
|
||||
AssertMsg(pObj->AttachObject(NULL,&defaultAttachment, FALSE, 0, -1, FALSE), "A default attachment could not be attached after merging, this should not be possible.");
|
||||
CreateItem(Item [ pObj->usItem ].defaultattachments[cnt],(*pObj)[ubStatusIndex]->data.objectStatus,&defaultAttachment);
|
||||
AssertMsg(pObj->AttachObject(NULL,&defaultAttachment, FALSE, ubStatusIndex, -1, FALSE), "A default attachment could not be attached after merging, this should not be possible.");
|
||||
}
|
||||
}
|
||||
|
||||
//First re-attach any slot-changing attachments.
|
||||
for (attachmentList::iterator iter = tempSlotChangingAttachList.begin(); iter != tempSlotChangingAttachList.end();) {
|
||||
if( ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE )){
|
||||
if( ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE, ubStatusIndex )){
|
||||
//This seems to be rather valid. Can't be 100% sure though.
|
||||
if(pObj->AttachObject(NULL, &(*iter), FALSE)){
|
||||
if(pObj->AttachObject(NULL, &(*iter), FALSE, ubStatusIndex)){
|
||||
//Ok now we can be sure, lets remove this object so we don't try to drop it later.
|
||||
iter = tempSlotChangingAttachList.erase(iter);
|
||||
} else {
|
||||
@@ -5365,9 +5389,9 @@ void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem)
|
||||
|
||||
//Time to re-attach the other attachments, if we can. I am the king of copy pasta.
|
||||
for (attachmentList::iterator iter = tempAttachList.begin(); iter != tempAttachList.end();) {
|
||||
if( ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE)){
|
||||
if( ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE, ubStatusIndex)){
|
||||
//This seems to be rather valid. Can't be 100% sure though.
|
||||
if(pObj->AttachObject(NULL, &(*iter), FALSE)){
|
||||
if(pObj->AttachObject(NULL, &(*iter), FALSE, ubStatusIndex)){
|
||||
//Ok now we can be sure, lets remove this object so we don't try to drop it later.
|
||||
iter = tempAttachList.erase(iter);
|
||||
} else {
|
||||
@@ -5385,7 +5409,9 @@ void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem)
|
||||
if (pSoldier) {
|
||||
if ( !AutoPlaceObject( pSoldier, &(*iter), FALSE ) )
|
||||
{ // put it on the ground
|
||||
AddItemToPool( pSoldier->sGridNo, &(*iter), 1, pSoldier->pathing.bLevel, 0 , -1 );
|
||||
// HEADROCK HAM 5: A much more suitable function. Works in both tactical and mapscreen!
|
||||
AutoPlaceObjectToWorld( pSoldier, &(*iter), true );
|
||||
//AddItemToPool( pSoldier->sGridNo, &(*iter), 1, pSoldier->pathing.bLevel, 0 , -1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5397,11 +5423,14 @@ void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem)
|
||||
if (pSoldier) {
|
||||
if ( !AutoPlaceObject( pSoldier, &(*iter), FALSE ) )
|
||||
{ // put it on the ground
|
||||
AddItemToPool( pSoldier->sGridNo, &(*iter), 1, pSoldier->pathing.bLevel, 0 , -1 );
|
||||
// HEADROCK HAM 5: A much more suitable function. Works in both tactical and mapscreen!
|
||||
AutoPlaceObjectToWorld( pSoldier, &(*iter), true );
|
||||
//AddItemToPool( pSoldier->sGridNo, &(*iter), 1, pSoldier->pathing.bLevel, 0 , -1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void EjectAmmoAndPlace(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT8 subObject)
|
||||
@@ -12597,3 +12626,339 @@ FLOAT GetItemCooldownFactor( OBJECTTYPE * pObj )
|
||||
|
||||
return cooldownfactor;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// HEADROCK HAM 5: Item Transformation.
|
||||
// Item Transformation is a new way to interact with items. Where Merges combine two items into one, a Transformation
|
||||
// can turn one item into another item, or into more than one item.
|
||||
// To instigate a Transformation, the player uses a menu to choose the desired effect. Then the program comes here to
|
||||
// see how it's done.
|
||||
// The instructions for performing a specific transformation are drawn from XML and fed into this function as a pointer.
|
||||
// They tell us what items will result from this transformation, as well as the APBP cost.
|
||||
|
||||
BOOLEAN OBJECTTYPE::TransformObject( SOLDIERTYPE * pSoldier, UINT8 ubStatusIndex, TransformInfoStruct * Transform, OBJECTTYPE *pParent )
|
||||
{
|
||||
// The argument "Transform" is a pointer to an entry in the Transformation Data array. By looking at the pointer we
|
||||
// can determine all the data we need. Therefore, this pointer must not be null!
|
||||
AssertMsg( Transform != NULL, String( "OBJECTTYPE::TransformObject attempt with invalid Transformation data." ) );
|
||||
|
||||
// Booleans to track what happened during the transformation.
|
||||
BOOLEAN fSplit = FALSE;
|
||||
BOOLEAN fDropped = FALSE;
|
||||
BOOLEAN fRemoved = FALSE;
|
||||
BOOLEAN fItemInPool = FALSE;
|
||||
|
||||
// This boolean tracks whether we've managed to place an item in a soldier's inventory.
|
||||
BOOLEAN fFoundPlaceInInventory = FALSE;
|
||||
|
||||
// Constants for storing details about the original item.
|
||||
OBJECTTYPE TempItem;
|
||||
UINT16 usOrigItem = this->usItem;
|
||||
UINT32 uiOrigClass = Item[this->usItem].usItemClass;
|
||||
UINT8 ubOrigNumObjects = this->ubNumberOfObjects;
|
||||
|
||||
UINT16 usAPCost = 0;
|
||||
INT32 iBPCost = 0;
|
||||
|
||||
// An array to store all result items.
|
||||
UINT16 usResult[MAX_NUM_TRANSFORMATION_RESULTS];
|
||||
UINT32 iNumResults = 0;
|
||||
|
||||
// Start reading transformation data with APBP costs.
|
||||
usAPCost = Transform->usAPCost;
|
||||
iBPCost = Transform->iBPCost;
|
||||
|
||||
// Check whether our soldier can afford this transformation!
|
||||
if (!EnoughPoints( pSoldier, (INT16)usAPCost, iBPCost, true ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Soldier can afford the transformation. Deduct APBP as necessary.
|
||||
DeductPoints( pSoldier, (INT16)usAPCost, iBPCost, false );
|
||||
}
|
||||
|
||||
// Read all result items for this transformation. Record them into an array.
|
||||
for (UINT32 curResult = 0; curResult < MAX_NUM_TRANSFORMATION_RESULTS; curResult++)
|
||||
{
|
||||
if (Transform->usResult[curResult] > 0)
|
||||
{
|
||||
usResult[curResult] = Transform->usResult[curResult];
|
||||
// Count the number of valid result items
|
||||
iNumResults++;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no result items, the Transformation is illegal - we need at least one resulting item!
|
||||
AssertMsg( iNumResults, String( "OBJECTTYPE::TransformObject attempting to transform an object which has no resulting items defined!" ) );
|
||||
|
||||
if (iNumResults > 1)
|
||||
{
|
||||
fSplit = TRUE;
|
||||
}
|
||||
|
||||
// Play a gun-cocking sound, it's the best one we've got ATM.
|
||||
PlayJA2Sample( ATTACH_TO_GUN, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
||||
|
||||
// Before we continue, lets check whether our object is in the sector inventory.
|
||||
// Is the sector inventory open?
|
||||
if (fShowMapInventoryPool)
|
||||
{
|
||||
// Is our object currently in the pool?
|
||||
for (UINT32 x = 0; x < pInventoryPoolList.size(); x++)
|
||||
{
|
||||
if (pInventoryPoolList[x].object.exists())
|
||||
{
|
||||
if (&(pInventoryPoolList[x].object) == this)
|
||||
{
|
||||
// Aha! In that case, all transformations will be done directly at the sector pool,
|
||||
// with multiple results ending on the ground rather than in the inventory.
|
||||
fItemInPool = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// The Transformation itself
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// We're going to do the transformation in steps, going hierarchially down from the item's own attachments,
|
||||
// to itsself, then its parents, and finally resulting items and unrelated inventory.
|
||||
// Note that we'll need to change the item's usItem property several times during this process, so lets
|
||||
// record its original usItem now.
|
||||
UINT16 usOldItem = this->usItem;
|
||||
|
||||
// STEP 1: Attachments and subsidiary objects.
|
||||
|
||||
// First of all, if the original item is a gun, we'll need to see if it can hold the same magazine after the
|
||||
// transformation. If it can't, the magazine will be ejected immediately into the soldier's inventory.
|
||||
|
||||
// Is this a gun, AND does it have any ammo loaded?
|
||||
if ( Item[this->usItem].usItemClass == IC_GUN && (*this)[ubStatusIndex]->data.gun.usGunAmmoItem != NONE && (*this)[ubStatusIndex]->data.gun.ubGunShotsLeft > 0 )
|
||||
{
|
||||
// Is the resulting item not a gun, OR is the resulting item of a different caliber, OR is the resulting item's
|
||||
// magazine too small?
|
||||
if ( Item[usResult[0]].usItemClass != IC_GUN || Weapon[Item[usResult[0]].ubClassIndex].ubCalibre != Weapon[Item[this->usItem].ubClassIndex].ubCalibre || (*this)[ubStatusIndex]->data.gun.ubGunShotsLeft > Weapon[Item[usResult[0]].ubClassIndex].ubMagSize )
|
||||
{
|
||||
// item types/calibers/magazines don't match, spit out old ammo
|
||||
EjectAmmoAndPlace(pSoldier, this);
|
||||
}
|
||||
}
|
||||
|
||||
// STEP 2: Check the item's attachments to see whether they still fit.
|
||||
// We'll have to fool this function into thinking we've already changed the item.
|
||||
// Note that this function automatically drops invalid attachments to the ground.
|
||||
this->usItem = usResult[0];
|
||||
// Repeat for each object in the stack.
|
||||
for ( UINT8 x = 0; x < this->ubNumberOfObjects; x++ )
|
||||
{
|
||||
ReInitMergedItem(pSoldier, this, usOldItem, x);
|
||||
}
|
||||
this->usItem = usOldItem;
|
||||
|
||||
//RemoveProhibitedAttachments(pSoldier, this, usOldItem);
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// TRANSFORM
|
||||
this->usItem = usResult[0];
|
||||
// Record the new itemclass
|
||||
UINT32 uiNewClass = Item[this->usItem].usItemClass;
|
||||
// Make a clone of this object, so that we can point the DescBox to it later if we run into any problems.
|
||||
gCloneItemDescObject = *(this);
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////
|
||||
// Placement checks
|
||||
|
||||
// Is the item an attachment? If so, check its parent to see if it's still compatible.
|
||||
if (pParent != NULL)
|
||||
{
|
||||
// When transforming an attachment, "THIS" is actually a copy of the object, called Object2. So transforming
|
||||
// "this" would only yield, at most, a superficial change (Description Box will change). The attachment item
|
||||
// itself will not change at all.
|
||||
|
||||
// Lets change the attachment item directly, then.
|
||||
gpItemDescOrigAttachmentObject->usItem = usResult[0];
|
||||
// Make a copy of it, so we know what data it contained.
|
||||
OBJECTTYPE pClone = *gpItemDescOrigAttachmentObject;
|
||||
|
||||
// Test the parent now. See whether all attachments are still valid on it.
|
||||
ReInitMergedItem(pSoldier, pParent, pParent->usItem, ubStatusIndex);
|
||||
|
||||
gpItemDescOrigAttachmentObject = NULL;
|
||||
|
||||
// After reiniting the attachments on the parent, "this" still exists, but the actual object is gone.
|
||||
// Lets look through the parent's attachments list, and see if we can find it again.
|
||||
UINT8 ubNewAttachmentsIndex = 0;
|
||||
for(attachmentList::iterator iter = (*pParent)[ubStatusIndex]->attachments.begin(); iter != (*pParent)[ubStatusIndex]->attachments.end(); iter++, ubNewAttachmentsIndex++)
|
||||
{
|
||||
if(iter->exists())
|
||||
{
|
||||
// Compare it to the clone we made earlier.
|
||||
if (*(iter) == pClone)
|
||||
{
|
||||
// Yes, here it is!
|
||||
gpItemDescOrigAttachmentObject = (*pParent)[ubStatusIndex]->GetAttachmentAtIndex( ubNewAttachmentsIndex );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Have we failed to find our item on the reinited parent?
|
||||
if (gpItemDescOrigAttachmentObject == NULL)
|
||||
{
|
||||
// It has been removed. Lets reset all the Description Box extra variables.
|
||||
// Note that by doing this, we actually trigger closing the description box later down the line.
|
||||
pParent = NULL;
|
||||
gfItemDescObjectIsAttachment = NULL;
|
||||
gpItemDescPrevObject = NULL;
|
||||
fRemoved = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Our object is not an attachment. If it is on a soldier, it may still not fit in the pocket where
|
||||
// it is currently placed, so lets see if we have to move it.
|
||||
else if (!fItemInPool)
|
||||
{
|
||||
for (INT8 bPocket = HELMETPOS; bPocket < NUM_INV_SLOTS; bPocket++)
|
||||
{
|
||||
if (&(pSoldier->inv[bPocket]) == this)
|
||||
{
|
||||
// Found our item. Does it fit in this slot?
|
||||
if (!CanItemFitInPosition(pSoldier, this, bPocket, FALSE) )
|
||||
{
|
||||
if (!AutoPlaceObject( pSoldier, this, TRUE ))
|
||||
{
|
||||
fDropped = TRUE;
|
||||
|
||||
AutoPlaceObjectToWorld( pSoldier, this, TRUE );
|
||||
|
||||
//Unfortunately the above function will not erase the item in tactical mode, so lets
|
||||
//double-check.
|
||||
if (pSoldier->inv[bPocket].exists() )
|
||||
{
|
||||
DeleteObj( &(pSoldier->inv[bPocket]) );
|
||||
}
|
||||
}
|
||||
// Whatever we've done with it, THIS is no longer a valid item, so lets
|
||||
// fool the desc box by switching it with the clone.
|
||||
gpItemDescObject = &gCloneItemDescObject;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If either the new or old items were LBEs, lets check the entire LBE inventory for item-size compatibility!
|
||||
//if (uiOrigClass & IC_LBEGEAR || uiNewClass & IC_LBEGEAR )
|
||||
if (!fItemInPool)
|
||||
{
|
||||
for (INT8 bPocket = HELMETPOS; bPocket < NUM_INV_SLOTS; bPocket++)
|
||||
{
|
||||
if (pSoldier->inv[bPocket].exists())
|
||||
{
|
||||
// Found an item. Does it still fit inside its own slot?
|
||||
if (!CanItemFitInPosition(pSoldier, &(pSoldier->inv[bPocket]), bPocket, FALSE) )
|
||||
{
|
||||
if (!AutoPlaceObject( pSoldier, &(pSoldier->inv[bPocket]), TRUE ))
|
||||
{
|
||||
fDropped = TRUE;
|
||||
|
||||
AutoPlaceObjectToWorld( pSoldier, &(pSoldier->inv[bPocket]), TRUE );
|
||||
|
||||
//Unfortunately the above function will not erase the item in tactical mode, so lets
|
||||
//double-check.
|
||||
if (pSoldier->inv[bPocket].exists() )
|
||||
{
|
||||
DeleteObj( &(pSoldier->inv[bPocket]) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
// Multiple Results
|
||||
//
|
||||
// If the item has several transformation results defined, that means we're going to split it into two or
|
||||
// more items.
|
||||
|
||||
// We actually start with any results above the first. This occurs if the item is split into two or more other
|
||||
// items. We'll try to place them in the pSoldier's inventory if possible, otherwise they are dumped to the
|
||||
// sector pool.
|
||||
|
||||
// Iterate through the results array we've constructed earlier.
|
||||
for (UINT32 x = 1; x < iNumResults; x++)
|
||||
{
|
||||
for (UINT32 y = 0; y < ubOrigNumObjects; y++)
|
||||
{
|
||||
// Create the result item. Set its condition to match that of the original.
|
||||
CreateItem( usResult[x], (*this)[ubStatusIndex]->data.objectStatus, &gTempObject );
|
||||
|
||||
if (!fItemInPool)
|
||||
{
|
||||
// Try placing it in the soldier's invnetory.
|
||||
if (!AutoPlaceObject( pSoldier, &gTempObject, TRUE ))
|
||||
{
|
||||
// Failed to find a place in the inventory. Dump to sector pool.
|
||||
AutoPlaceObjectToWorld( pSoldier, &gTempObject, true );
|
||||
|
||||
fDropped = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AutoPlaceObjectToWorld( pSoldier, &gTempObject, true );
|
||||
}
|
||||
|
||||
// Cleanup after the autoplace has to occur in tactical mode.
|
||||
if (gTempObject.exists())
|
||||
{
|
||||
DeleteObj( &(gTempObject) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check the soldier to see how his stats have changed as a result of altering his gear.
|
||||
ApplyEquipmentBonuses(pSoldier);
|
||||
|
||||
if (fItemInPool && fSplit)
|
||||
{
|
||||
CHAR16 pStr[500];
|
||||
// Item was split apart. Since it was in the sector inventory, it's common sense that all results
|
||||
// are in the sector inventory as well, so no need to report anything extra.
|
||||
swprintf( pStr, gzTransformationMessage[ 1 ], Item[usOrigItem].szItemName, pSoldier->name );
|
||||
ScreenMsg( FONT_ORANGE, MSG_INTERFACE, pStr );
|
||||
}
|
||||
else if (fSplit || fDropped)
|
||||
{
|
||||
CHAR16 pStr[500];
|
||||
if (fSplit && !fDropped)
|
||||
{
|
||||
// Item was split apart, but all subitems remained in the inventory.
|
||||
swprintf( pStr, gzTransformationMessage[ 2 ], Item[usOrigItem].szItemName, pSoldier->name );
|
||||
ScreenMsg( FONT_ORANGE, MSG_INTERFACE, pStr );
|
||||
}
|
||||
else if (fDropped && !fSplit)
|
||||
{
|
||||
// Either the item itself or another item has been dropped to the sector inventory due to lack of
|
||||
// space.
|
||||
swprintf( pStr, gzTransformationMessage[ 3 ], pSoldier->name );
|
||||
DoScreenIndependantMessageBox( pStr, MSG_BOX_FLAG_OK, NULL );
|
||||
}
|
||||
else if (fDropped && fSplit)
|
||||
{
|
||||
// Item was split apart. Either the item itself or another item has been dropped to the sector
|
||||
// inventory due to lack of space.
|
||||
swprintf( pStr, gzTransformationMessage[ 4 ], Item[usOrigItem].szItemName, pSoldier->name );
|
||||
DoScreenIndependantMessageBox( pStr, MSG_BOX_FLAG_OK, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
// Signal a successful transformation.
|
||||
return TRUE;
|
||||
}
|
||||
+2
-1
@@ -111,7 +111,8 @@ void RemoveInvObject( SOLDIERTYPE *pSoldier, UINT16 usItem );
|
||||
void InitItemAttachments(OBJECTTYPE* pObj);
|
||||
std::vector<UINT16> GetItemSlots(OBJECTTYPE* pObj, UINT8 subObject = 0, BOOLEAN fAttachment = FALSE);
|
||||
void RemoveProhibitedAttachments(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usItem, BOOLEAN fOnlyRemoveWhenSlotsChange = 1);
|
||||
void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem);
|
||||
// HEADROCK HAM 5: Added argument for statusindex.
|
||||
void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem, UINT8 ubStatusIndex);
|
||||
void EjectAmmoAndPlace(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT8 subObject = 0);
|
||||
|
||||
BOOLEAN CanItemFitInVehicle( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 bPos, BOOLEAN fDoingPlacement );
|
||||
|
||||
+997
-360
File diff suppressed because it is too large
Load Diff
+6
-1
@@ -67,6 +67,8 @@ INT8 ChanceToGetThrough( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOAT d
|
||||
INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ, UINT16 usHandItem, INT16 sHitBy, BOOLEAN fBuckshot, BOOLEAN fFake );
|
||||
// HEADROCK HAM 4: Changed the name of one argument to avoid confusion with the new CTH system.
|
||||
INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ, UINT16 usHandItem, INT16 sApertureRatio, BOOLEAN fBuckshot, BOOLEAN fFake );
|
||||
// HEADROCK HAM 5: Function for fragments ejected from an explosion.
|
||||
INT8 FireFragmentGivenTarget( SOLDIERTYPE * pThrower, FLOAT dStartX, FLOAT dStartY, FLOAT dStartZ, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ, UINT16 usExplosiveItem );
|
||||
|
||||
#define CALC_FROM_ALL_DIRS -1
|
||||
#define CALC_FROM_WANTED_DIR -2
|
||||
@@ -223,11 +225,14 @@ void CalcMuzzleSway( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetX, FLOAT *dMuzzl
|
||||
FLOAT CalcBulletDeviation( SOLDIERTYPE *pShooter, FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, OBJECTTYPE *pWeapon, UINT32 uiRange );
|
||||
void LimitImpactPointByFacing( SOLDIERTYPE *pShooter, SOLDIERTYPE *pTarget, FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, FLOAT *dEndX, FLOAT *dEndY );
|
||||
void LimitImpactPointToMaxAperture( FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, FLOAT dDistanceAperture );
|
||||
UINT32 CalcCounterForceFrequency(SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon);
|
||||
// HEADROCK HAM 5: Removed and replaced by continuously-variable CF
|
||||
// UINT32 CalcCounterForceFrequency(SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon);
|
||||
FLOAT CalcCounterForceMax(SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, UINT8 uiStance = 0);
|
||||
UINT32 CalcCounterForceAccuracy(SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, UINT32 uiRange, BOOLEAN fTracer, bool fAnticipate = false);
|
||||
void CalcPreRecoilOffset( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT *dMuzzleOffsetX, FLOAT *dMuzzleOffsetY, UINT32 uiRange );
|
||||
void CalcRecoilOffset( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetX, FLOAT *dMuzzleOffsetY, OBJECTTYPE *pWeapon, UINT32 uiRange );
|
||||
// HEADROCK HAM 5: New function, completely replaces the Counter Force Frequency check.
|
||||
FLOAT CalcCounterForceChange( SOLDIERTYPE * pShooter, UINT32 uiCounterForceAccuracy, FLOAT dCounterForceMax, FLOAT dMuzzleOffset, INT8 bRecoil, FLOAT dPrevCounterForce, UINT32 uiIntendedBullets );
|
||||
|
||||
// HEADROCK HAM 4: Required for shooting mechanic
|
||||
extern INT8 EffectiveMarksmanship( SOLDIERTYPE * pSoldier );
|
||||
|
||||
@@ -1077,8 +1077,8 @@ BOOLEAN CheckIfRadioIsEquipped( void )
|
||||
|
||||
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
||||
{
|
||||
bSlot = FindObj( pSoldier, EXTENDEDEAR );
|
||||
//bSlot = FindHearingAid(pSoldier);
|
||||
//bSlot = FindObj( pSoldier, EXTENDEDEAR );
|
||||
bSlot = FindHearingAid(pSoldier);
|
||||
//ScreenMsg( FONT_WHITE, MSG_INTERFACE, L"Position: %d", bSlot );
|
||||
}
|
||||
|
||||
|
||||
@@ -2692,7 +2692,6 @@ INT16 GetAPsToAutoReload( SOLDIERTYPE * pSoldier )
|
||||
{
|
||||
// Flugente: check for underbarrel weapons and use that object if necessary
|
||||
pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[SECONDHANDPOS]) );
|
||||
|
||||
bExcludeSlot = NO_SLOT;
|
||||
bSlot2 = NO_SLOT;
|
||||
|
||||
|
||||
+25
-11
@@ -80,10 +80,11 @@ class SOLDIERTYPE;
|
||||
#define DROP_LENGTH_CHANGE_RATE 0.1f
|
||||
#define DROP_LENGTH_RAND 2.0f
|
||||
|
||||
#define BASE_DROP_SPEED 7.0f
|
||||
#define DROP_SPEED_RANGE 3.5f
|
||||
#define DROP_SPEED_CHANGE_RATE 0.1f
|
||||
#define DROP_SPEED_RAND 5.0f
|
||||
// HEADROCK HAM 5 X: Externalized for snow.
|
||||
FLOAT BASE_DROP_SPEED;
|
||||
FLOAT DROP_SPEED_RANGE;
|
||||
FLOAT DROP_SPEED_CHANGE_RATE;
|
||||
FLOAT DROP_SPEED_RAND;
|
||||
|
||||
UINT32 guiMaxRainDrops = 79;
|
||||
|
||||
@@ -203,11 +204,18 @@ void ResetRain()
|
||||
pRainDrops = NULL;
|
||||
}
|
||||
|
||||
// Rain
|
||||
BASE_DROP_SPEED = 7.0f;
|
||||
DROP_SPEED_RANGE = 3.5f;
|
||||
DROP_SPEED_CHANGE_RATE = 0.1f;
|
||||
DROP_SPEED_RAND = 5.0f;
|
||||
|
||||
guiCurrMaxAmountOfRainDrops = 0;
|
||||
}
|
||||
|
||||
void GenerateRainDropsList()
|
||||
{
|
||||
// HEADROCK HAM 5 XMAS: More snow than rain.
|
||||
guiCurrMaxAmountOfRainDrops = (UINT32)(BASE_MAXIMUM_DROPS) * gbCurrentRainIntensity;
|
||||
|
||||
pRainDrops = (TRainDrop *)MemAlloc( sizeof( TRainDrop ) * guiCurrMaxAmountOfRainDrops );
|
||||
@@ -415,6 +423,7 @@ void RenderRainOnSurface()
|
||||
|
||||
if( !pCurr->fAlive )continue;
|
||||
|
||||
// Rain
|
||||
LineDraw( TRUE, (int)pCurr->fpX, (int)pCurr->fpY, (int)pCurr->fpX + (int)pCurr->fpEndRelX, (int)(pCurr->fpY + pCurr->fpEndRelY), sDropsColor, pDestBuf );
|
||||
}
|
||||
|
||||
@@ -427,14 +436,19 @@ void GenerateRainMaximums()
|
||||
{
|
||||
fpMinDropAngleOfFalling = 45;
|
||||
fpMaxDropAngleOfFalling = 135;
|
||||
}else
|
||||
if( Random( 2 ) )
|
||||
}
|
||||
else
|
||||
{
|
||||
fpMinDropAngleOfFalling = 20;
|
||||
fpMaxDropAngleOfFalling = 70;
|
||||
}else{
|
||||
fpMinDropAngleOfFalling = 110;
|
||||
fpMaxDropAngleOfFalling = 160;
|
||||
if( Random( 2 ) )
|
||||
{
|
||||
fpMinDropAngleOfFalling = 20;
|
||||
fpMaxDropAngleOfFalling = 70;
|
||||
}
|
||||
else
|
||||
{
|
||||
fpMinDropAngleOfFalling = 110;
|
||||
fpMaxDropAngleOfFalling = 160;
|
||||
}
|
||||
}
|
||||
|
||||
fpCurrDropAngleOfFalling = fpMinDropAngleOfFalling + Random( (UINT32)(fpMaxDropAngleOfFalling - fpMinDropAngleOfFalling) );
|
||||
|
||||
@@ -74,6 +74,8 @@
|
||||
#define MAX_PALACE_DISTANCE 20
|
||||
|
||||
INT8 bNumSquadleadersInArmy = 0; // added by SANDRO
|
||||
// HEADROCK HAM 5: Read target coolness by sector
|
||||
UINT32 gCoolnessBySector[256];
|
||||
|
||||
OLD_SOLDIERCREATE_STRUCT_101::OLD_SOLDIERCREATE_STRUCT_101() {
|
||||
initialize();
|
||||
@@ -3237,8 +3239,8 @@ UINT8 GetLocationModifier( UINT8 ubSoldierClass )
|
||||
INT16 sSectorX, sSectorY, sSectorZ;
|
||||
#ifdef JA2UB
|
||||
#else
|
||||
INT8 bTownId;
|
||||
UINT8 ubPalaceDistance;
|
||||
//INT8 bTownId;
|
||||
//UINT8 ubPalaceDistance;
|
||||
#endif
|
||||
BOOLEAN fSuccess;
|
||||
|
||||
@@ -3372,6 +3374,13 @@ UINT8 GetLocationModifier( UINT8 ubSoldierClass )
|
||||
break;
|
||||
}
|
||||
#else
|
||||
// HEADROCK HAM 5:
|
||||
// The calculation has been replaced with an XML table.
|
||||
|
||||
ubLocationModifier = gCoolnessBySector[SECTOR(sSectorX, sSectorY)];
|
||||
|
||||
/*
|
||||
|
||||
// ignore sSectorZ - treat any underground enemies as if they were on the surface!
|
||||
bTownId = GetTownIdForSector( sSectorX, sSectorY );
|
||||
|
||||
@@ -3401,6 +3410,8 @@ UINT8 GetLocationModifier( UINT8 ubSoldierClass )
|
||||
|
||||
// adjust for distance from Queen's palace (P3) (0 to +30)
|
||||
ubLocationModifier = ( ( MAX_PALACE_DISTANCE - ubPalaceDistance ) * DIFF_FACTOR_PALACE_DISTANCE ) / MAX_PALACE_DISTANCE;
|
||||
*/
|
||||
|
||||
#endif
|
||||
return( ubLocationModifier );
|
||||
}
|
||||
|
||||
@@ -207,8 +207,10 @@
|
||||
<ClCompile Include="XML_HiddenNames.cpp" />
|
||||
<ClCompile Include="XML_IMPItemChoices.cpp" />
|
||||
<ClCompile Include="XML_IncompatibleAttachments.cpp" />
|
||||
<ClCompile Include="XML_ItemAdjustments.cpp" />
|
||||
<ClCompile Include="XML_Launchable.cpp" />
|
||||
<ClCompile Include="XML_LBEPocket.cpp" />
|
||||
<ClCompile Include="XML_LBEPocketPopup.cpp" />
|
||||
<ClCompile Include="XML_LoadBearingEquipment.cpp" />
|
||||
<ClCompile Include="XML_Magazine.cpp" />
|
||||
<ClCompile Include="XML_MercStartingGear.cpp" />
|
||||
|
||||
@@ -611,5 +611,11 @@
|
||||
<ClCompile Include="Ja25_Tactical.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_LBEPocketPopup.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_ItemAdjustments.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
+251
-102
@@ -1747,9 +1747,19 @@ BOOLEAN UseGunNCTH( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
OBJECTTYPE* pA= &(*iter);
|
||||
if ( (*pA)[0]->data.objectStatus >=USABLE)
|
||||
{
|
||||
INT8 bAmmoReliability = Item[(*pObjAttHand)[0]->data.gun.usGunAmmoItem].bReliability;
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 *
|
||||
(Item[ iter->usItem ].bReliability + bAmmoReliability), 0);
|
||||
INT16 ammoReliability = Item[(*pObjAttHand)[0]->data.gun.usGunAmmoItem].bReliability;
|
||||
// HEADROCK HAM 5: Variable base chance
|
||||
if ( UsingNewCTHSystem() == true)
|
||||
{
|
||||
UINT16 usBaseChance = gGameCTHConstants.BASIC_RELIABILITY_ODDS;
|
||||
FLOAT dReliabilityRatio = 3.0f * ((FLOAT)usBaseChance / (FLOAT)BASIC_DEPRECIATE_CHANCE); // Compare original odds to new odds.
|
||||
uiDepreciateTest = usBaseChance + (INT16)( dReliabilityRatio * (Item[ iter->usItem ].bReliability + ammoReliability) );
|
||||
uiDepreciateTest = max(0, uiDepreciateTest);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiDepreciateTest = max(0,BASIC_DEPRECIATE_CHANCE + 3 * (Item[ iter->usItem ].bReliability + ammoReliability));
|
||||
}
|
||||
if ( !PreRandom( uiDepreciateTest ) && ( (*pObjAttHand)[0]->data.objectStatus > 1) )
|
||||
(*pA)[0]->data.objectStatus--;
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"rel =%d ",Item[ iter->usItem ].bReliability );
|
||||
@@ -2107,8 +2117,18 @@ BOOLEAN UseGunNCTH( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
//}
|
||||
|
||||
// Flugente FTW 1: Added a malus to reliability for overheated guns
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 * GetReliability( pObjAttHand ) - iOverheatReliabilityMalus, 0);
|
||||
|
||||
// HEADROCK HAM 5: Variable NCTH base change
|
||||
if ( UsingNewCTHSystem() == true)
|
||||
{
|
||||
UINT16 usBaseChance = gGameCTHConstants.BASIC_RELIABILITY_ODDS;
|
||||
FLOAT dReliabilityRatio = 3.0f * ((FLOAT)usBaseChance / (FLOAT)BASIC_DEPRECIATE_CHANCE); // Compare original odds to new odds.
|
||||
uiDepreciateTest = usBaseChance + (INT16)( dReliabilityRatio * GetReliability( &(pSoldier->inv[pSoldier->ubAttackingHand]) - iOverheatReliabilityMalus) );
|
||||
uiDepreciateTest = max(0, uiDepreciateTest);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 * GetReliability( pObjAttHand ) - iOverheatReliabilityMalus, 0);
|
||||
}
|
||||
if ( !PreRandom( uiDepreciateTest ) && ( (*pObjAttHand)[0]->data.objectStatus > 1) )
|
||||
{
|
||||
(*pObjAttHand)[0]->data.objectStatus--;
|
||||
@@ -2284,9 +2304,19 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
OBJECTTYPE* pA= &(*iter);
|
||||
if ( (*pA)[0]->data.objectStatus >=USABLE)
|
||||
{
|
||||
INT8 bAmmoReliability = Item[(*pObjUsed)[0]->data.gun.usGunAmmoItem].bReliability;
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 *
|
||||
(Item[ iter->usItem ].bReliability + bAmmoReliability), 0);
|
||||
INT16 ammoReliability = Item[(*pObjUsed)[0]->data.gun.usGunAmmoItem].bReliability;
|
||||
// HEADROCK HAM 5: Variable base chance
|
||||
if ( UsingNewCTHSystem() == true )
|
||||
{
|
||||
UINT16 usBaseChance = gGameCTHConstants.BASIC_RELIABILITY_ODDS;
|
||||
FLOAT dReliabilityRatio = 3.0f * ((FLOAT)usBaseChance / (FLOAT)BASIC_DEPRECIATE_CHANCE); // Compare original odds to new odds.
|
||||
uiDepreciateTest = usBaseChance + (INT16)( dReliabilityRatio * (Item[ iter->usItem ].bReliability + ammoReliability) );
|
||||
uiDepreciateTest = __max(0, uiDepreciateTest);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiDepreciateTest = __max(0,BASIC_DEPRECIATE_CHANCE + 3 * (Item[ iter->usItem ].bReliability + ammoReliability));
|
||||
}
|
||||
if ( !PreRandom( uiDepreciateTest ) && ( (*pObjUsed)[0]->data.objectStatus > 1) )
|
||||
(*pA)[0]->data.objectStatus--;
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"rel =%d ",Item[ iter->usItem ].bReliability );
|
||||
@@ -2675,7 +2705,17 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
*/
|
||||
|
||||
// Flugente FTW 1: Added a malus to reliability for overheated guns
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 * ( GetReliability( pObjUsed ) ) - iOverheatReliabilityMalus, 0);
|
||||
if ( UsingNewCTHSystem() == true )
|
||||
{
|
||||
UINT16 usBaseChance = gGameCTHConstants.BASIC_RELIABILITY_ODDS;
|
||||
FLOAT dReliabilityRatio = 3.0f * ((FLOAT)usBaseChance / (FLOAT)BASIC_DEPRECIATE_CHANCE); // Compare original odds to new odds.
|
||||
uiDepreciateTest = usBaseChance + (INT16)( dReliabilityRatio * GetReliability( &(pSoldier->inv[ pSoldier->ubAttackingHand ])) - iOverheatReliabilityMalus);
|
||||
uiDepreciateTest = max(0, uiDepreciateTest);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 * ( GetReliability( pObjUsed ) ) - iOverheatReliabilityMalus, 0);
|
||||
}
|
||||
|
||||
if ( !PreRandom( uiDepreciateTest ) && ( (*pObjUsed)[0]->data.objectStatus > 1) )
|
||||
{
|
||||
@@ -4003,14 +4043,27 @@ void WeaponHit( UINT16 usSoldierID, UINT16 usWeaponIndex, INT16 sDamage, INT16 s
|
||||
MakeNoise( ubAttackerID, pTargetSoldier->sGridNo, pTargetSoldier->pathing.bLevel, gpWorldLevelData[pTargetSoldier->sGridNo].ubTerrainID, Weapon[ usWeaponIndex ].ubHitVolume, NOISE_BULLET_IMPACT );
|
||||
|
||||
// CALLAHAN START BUGFIX
|
||||
if ( EXPLOSIVE_GUN( usWeaponIndex ) || AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1)
|
||||
// Provisions for Fragments, which are resulting from a different weapon than the one we are holding in our hand.
|
||||
UINT8 ubAmmoType = 0;
|
||||
if ( pObj->usItem == usWeaponIndex )
|
||||
{
|
||||
ubAmmoType = (*pObj)[0]->data.gun.ubGunAmmoType;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Must be a fragment.
|
||||
ubAmmoType = Explosive[Item[usWeaponIndex].ubClassIndex].ubFragType;
|
||||
usWeaponIndex = 1; // Set to default gun.
|
||||
}
|
||||
|
||||
if ( EXPLOSIVE_GUN( usWeaponIndex ) || AmmoTypes[ubAmmoType].explosionSize > 1)
|
||||
// CALLAHAN END BUGFIX
|
||||
{
|
||||
// Reduce attacker count!
|
||||
//TODO: Madd --- I don't think this code will ever get called for the HE ammo -- the EXPLOSIVE_GUN check filters out regular guns
|
||||
// marke test mag ammo type: pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.ubGunAmmoType
|
||||
// 2cond 'or' added
|
||||
if ( Item[usWeaponIndex].rocketlauncher || AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1 )
|
||||
if ( Item[usWeaponIndex].rocketlauncher || AmmoTypes[ubAmmoType].explosionSize > 1 )
|
||||
{
|
||||
if ( Item[usWeaponIndex].singleshotrocketlauncher )
|
||||
{
|
||||
@@ -4032,15 +4085,16 @@ void WeaponHit( UINT16 usSoldierID, UINT16 usWeaponIndex, INT16 sDamage, INT16 s
|
||||
pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
}
|
||||
}
|
||||
else if ( AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1)
|
||||
else if ( AmmoTypes[ubAmmoType].explosionSize > 1)
|
||||
{
|
||||
// re-routed the Highexplosive value to define exposion type
|
||||
IgniteExplosion( ubAttackerID, sXPos, sYPos, 0, GETWORLDINDEXFROMWORLDCOORDS( sYPos, sXPos ), AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].highExplosive , pTargetSoldier->pathing.bLevel );
|
||||
IgniteExplosion( ubAttackerID, sXPos, sYPos, 0, GETWORLDINDEXFROMWORLDCOORDS( sYPos, sXPos ), AmmoTypes[ubAmmoType].highExplosive , pTargetSoldier->pathing.bLevel );
|
||||
// pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
}
|
||||
}
|
||||
else // tank cannon
|
||||
{
|
||||
// HEADROCK HAM 5 TODO: TANK_SHELL!
|
||||
IgniteExplosion( ubAttackerID, sXPos, sYPos, 0, GETWORLDINDEXFROMWORLDCOORDS( sYPos, sXPos ), TANK_SHELL, pTargetSoldier->pathing.bLevel );
|
||||
}
|
||||
|
||||
@@ -4088,10 +4142,29 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
|
||||
// Flugente: check for underbarrel weapons and use that object if necessary
|
||||
pObj = MercPtrs[ ubAttackerID ]->GetUsedWeapon( &MercPtrs [ ubAttackerID ]->inv[MercPtrs[ubAttackerID]->ubAttackingHand] );
|
||||
|
||||
if ( fStopped && ubAttackerID != NOBODY )
|
||||
// Get attacker
|
||||
if (ubAttackerID != NOBODY)
|
||||
{
|
||||
pAttacker = MercPtrs[ ubAttackerID ];
|
||||
}
|
||||
|
||||
// HEADROCK HAM 5: Define differently for fragments
|
||||
UINT8 ubHitVolume = 0;
|
||||
UINT8 ubAmmoType = 0;
|
||||
|
||||
if (pBullet->fFragment)
|
||||
{
|
||||
ubHitVolume = 1;
|
||||
ubAmmoType = Explosive[Item[pBullet->fromItem].ubClassIndex].ubFragType;
|
||||
}
|
||||
else
|
||||
{
|
||||
ubHitVolume = Weapon[usWeaponIndex].ubHitVolume;
|
||||
ubAmmoType = (*pObj)[0]->data.gun.ubGunAmmoType;
|
||||
}
|
||||
|
||||
if ( fStopped && ubAttackerID != NOBODY )
|
||||
{
|
||||
if ( pAttacker->ubOppNum != NOBODY )
|
||||
{
|
||||
// if it was another team shooting at someone under our control
|
||||
@@ -4124,11 +4197,11 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
|
||||
|
||||
if (sZPos > WALL_HEIGHT)
|
||||
{
|
||||
MakeNoise( ubAttackerID, sGridNo, 1, gpWorldLevelData[sGridNo].ubTerrainID, Weapon[ usWeaponIndex ].ubHitVolume, NOISE_BULLET_IMPACT );
|
||||
MakeNoise( ubAttackerID, sGridNo, 1, gpWorldLevelData[sGridNo].ubTerrainID, ubHitVolume, NOISE_BULLET_IMPACT );
|
||||
}
|
||||
else
|
||||
{
|
||||
MakeNoise( ubAttackerID, sGridNo, 0, gpWorldLevelData[sGridNo].ubTerrainID, Weapon[ usWeaponIndex ].ubHitVolume, NOISE_BULLET_IMPACT );
|
||||
MakeNoise( ubAttackerID, sGridNo, 0, gpWorldLevelData[sGridNo].ubTerrainID, ubHitVolume, NOISE_BULLET_IMPACT );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4146,30 +4219,35 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
|
||||
// Reduce attacker count!
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - end of LAW fire") );
|
||||
// FreeUpAttacker( ubAttackerID );
|
||||
if ( Item[usWeaponIndex].singleshotrocketlauncher )
|
||||
// HEADROCK HAM 5: Fragments fired by such weapons should not explode.
|
||||
if ( pBullet->fFragment == false)
|
||||
{
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, C1, (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
}
|
||||
// changed too to use 2 flag to determine
|
||||
else if ( !Item[usWeaponIndex].singleshotrocketlauncher && Item[usWeaponIndex].rocketlauncher)
|
||||
//there shouldn't be a way to enter here with an UnderBarrel weapon, so retaining original code :JMich
|
||||
{
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("StructureHit: RPG7 item: %d, Ammo: %d",pAttacker->inv[HANDPOS].usItem , pAttacker->inv[HANDPOS][0]->data.gun.usGunAmmoItem ) );
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem , (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
|
||||
//This is just to make multishot launchers work in semi auto. It's not really a permanent solution because it still doesn't allow autofire, but it will do for now.
|
||||
OBJECTTYPE * pLaunchable = FindLaunchableAttachment( &(pAttacker->inv[pAttacker->ubAttackingHand ]), pAttacker->inv[pAttacker->ubAttackingHand ].usItem );
|
||||
if(pLaunchable){
|
||||
pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem = pLaunchable->usItem;
|
||||
} else {
|
||||
pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
if ( Item[usWeaponIndex].singleshotrocketlauncher )
|
||||
{
|
||||
// HEADROCK HAM 5 TODO: C1!!!
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, C1, (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
}
|
||||
// changed too to use 2 flag to determine
|
||||
else if ( !Item[usWeaponIndex].singleshotrocketlauncher && Item[usWeaponIndex].rocketlauncher)
|
||||
//there shouldn't be a way to enter here with an UnderBarrel weapon, so retaining original code :JMich
|
||||
{
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("StructureHit: RPG7 item: %d, Ammo: %d",pAttacker->inv[HANDPOS].usItem , pAttacker->inv[HANDPOS][0]->data.gun.usGunAmmoItem ) );
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem , (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
|
||||
//This is just to make multishot launchers work in semi auto. It's not really a permanent solution because it still doesn't allow autofire, but it will do for now.
|
||||
OBJECTTYPE * pLaunchable = FindLaunchableAttachment( &(pAttacker->inv[pAttacker->ubAttackingHand ]), pAttacker->inv[pAttacker->ubAttackingHand ].usItem );
|
||||
if(pLaunchable){
|
||||
pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem = pLaunchable->usItem;
|
||||
} else {
|
||||
pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
}
|
||||
}
|
||||
else if ( AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1)
|
||||
{
|
||||
// re-routed the Highexplosive value to define exposion type
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, AmmoTypes[ (*pObj)[0]->data.gun.ubGunAmmoType].highExplosive , (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
// pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
}
|
||||
}
|
||||
else if ( AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1)
|
||||
{
|
||||
// re-routed the Highexplosive value to define exposion type
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, AmmoTypes[ (*pObj)[0]->data.gun.ubGunAmmoType].highExplosive , (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
// pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
}
|
||||
|
||||
// Moved here to make sure ABC stays >0 until everything done
|
||||
@@ -4184,6 +4262,7 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
|
||||
//DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - end of TANK fire") );
|
||||
//FreeUpAttacker( ubAttackerID );
|
||||
|
||||
// HEADROCK HAM 5 TODO: Tank shell!!
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, TANK_SHELL, (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
//FreeUpAttacker( (UINT8) ubAttackerID );
|
||||
|
||||
@@ -4202,67 +4281,83 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
|
||||
DamageStructure( pStructure, (UINT8)iImpact, STRUCTURE_DAMAGE_GUNFIRE, sGridNo, sXPos, sYPos, ubAttackerID );
|
||||
}
|
||||
|
||||
switch( Weapon[ usWeaponIndex ].ubWeaponClass )
|
||||
// HEADROCK HAM 5: Fragments are not fired from guns, so they need a special case.
|
||||
if (pBullet->fFragment == false)
|
||||
{
|
||||
case HANDGUNCLASS:
|
||||
case RIFLECLASS:
|
||||
case SHOTGUNCLASS:
|
||||
case SMGCLASS:
|
||||
case MGCLASS:
|
||||
switch( Weapon[ usWeaponIndex ].ubWeaponClass )
|
||||
{
|
||||
case HANDGUNCLASS:
|
||||
case RIFLECLASS:
|
||||
case SHOTGUNCLASS:
|
||||
case SMGCLASS:
|
||||
case MGCLASS:
|
||||
|
||||
// Guy has missed, play random sound
|
||||
if ( MercPtrs[ ubAttackerID ]->bTeam == gbPlayerNum )
|
||||
{
|
||||
if ( !MercPtrs[ ubAttackerID ]->bDoBurst )
|
||||
// Guy has missed, play random sound
|
||||
if ( MercPtrs[ ubAttackerID ]->bTeam == gbPlayerNum )
|
||||
{
|
||||
if ( Random( 40 ) == 0 )
|
||||
if ( !MercPtrs[ ubAttackerID ]->bDoBurst )
|
||||
{
|
||||
MercPtrs[ ubAttackerID ]->DoMercBattleSound( BATTLE_SOUND_CURSE1 );
|
||||
if ( Random( 40 ) == 0 )
|
||||
{
|
||||
MercPtrs[ ubAttackerID ]->DoMercBattleSound( BATTLE_SOUND_CURSE1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//fDoMissForGun = TRUE;
|
||||
//break;
|
||||
fDoMissForGun = TRUE;
|
||||
break;
|
||||
//fDoMissForGun = TRUE;
|
||||
//break;
|
||||
fDoMissForGun = TRUE;
|
||||
break;
|
||||
|
||||
case MONSTERCLASS:
|
||||
case MONSTERCLASS:
|
||||
|
||||
DoSpecialEffectAmmoMiss( ubAttackerID, sGridNo, sXPos, sYPos, sZPos, FALSE, TRUE, iBullet );
|
||||
|
||||
RemoveBullet( iBullet );
|
||||
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - monster attack hit structure") );
|
||||
// FreeUpAttacker( (UINT8) ubAttackerID );
|
||||
|
||||
//PlayJA2Sample( SPIT_RICOCHET , RATE_11025, uiMissVolume, 1, SoundDir( sGridNo ) );
|
||||
break;
|
||||
|
||||
case KNIFECLASS:
|
||||
|
||||
// When it hits the ground, leave on map...
|
||||
if ( Item[ usWeaponIndex ].usItemClass == IC_THROWING_KNIFE )
|
||||
{
|
||||
// OK, have we hit ground?
|
||||
if ( usStructureID == INVALID_STRUCTURE_ID )
|
||||
{
|
||||
// Add item
|
||||
CreateItem( usWeaponIndex, bWeaponStatus, &gTempObject );
|
||||
|
||||
AddItemToPool( sGridNo, &gTempObject, -1 , 0, 0, -1 );
|
||||
|
||||
// Make team look for items
|
||||
NotifySoldiersToLookforItems( );
|
||||
}
|
||||
|
||||
if ( !fHitSameStructureAsBefore )
|
||||
{
|
||||
PlayJA2Sample( MISS_KNIFE, RATE_11025, uiMissVolume, 1, SoundDir( sGridNo ) );
|
||||
}
|
||||
DoSpecialEffectAmmoMiss( ubAttackerID, sGridNo, sXPos, sYPos, sZPos, FALSE, TRUE, iBullet );
|
||||
|
||||
RemoveBullet( iBullet );
|
||||
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - knife attack hit structure") );
|
||||
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - monster attack hit structure") );
|
||||
// FreeUpAttacker( (UINT8) ubAttackerID );
|
||||
}
|
||||
|
||||
//PlayJA2Sample( SPIT_RICOCHET , RATE_11025, uiMissVolume, 1, SoundDir( sGridNo ) );
|
||||
break;
|
||||
|
||||
case KNIFECLASS:
|
||||
|
||||
// When it hits the ground, leave on map...
|
||||
if ( Item[ usWeaponIndex ].usItemClass == IC_THROWING_KNIFE )
|
||||
{
|
||||
// OK, have we hit ground?
|
||||
if ( usStructureID == INVALID_STRUCTURE_ID )
|
||||
{
|
||||
// Add item
|
||||
CreateItem( usWeaponIndex, bWeaponStatus, &gTempObject );
|
||||
|
||||
AddItemToPool( sGridNo, &gTempObject, -1 , 0, 0, -1 );
|
||||
|
||||
// Make team look for items
|
||||
NotifySoldiersToLookforItems( );
|
||||
}
|
||||
|
||||
if ( !fHitSameStructureAsBefore )
|
||||
{
|
||||
PlayJA2Sample( MISS_KNIFE, RATE_11025, uiMissVolume, 1, SoundDir( sGridNo ) );
|
||||
}
|
||||
|
||||
RemoveBullet( iBullet );
|
||||
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - knife attack hit structure") );
|
||||
// FreeUpAttacker( (UINT8) ubAttackerID );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( sZPos == 0 )
|
||||
{
|
||||
PlayJA2Sample( MISS_G2 , RATE_11025, 5, 1, SoundDir( sGridNo ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayJA2Sample( MISS_1 + Random(8), RATE_11025, 5, 1, SoundDir( sGridNo ) );
|
||||
}
|
||||
RemoveBullet( iBullet );
|
||||
}
|
||||
|
||||
if ( fDoMissForGun )
|
||||
@@ -8442,8 +8537,24 @@ INT32 TotalArmourProtection( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 u
|
||||
return( iTotalProtection );
|
||||
}
|
||||
|
||||
INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 iOrigImpact, INT16 sHitBy, UINT8 * pubSpecial )
|
||||
// HEADROCK HAM 5: Added argument the bullet!
|
||||
INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 iOrigImpact, INT16 sHitBy, UINT8 * pubSpecial )
|
||||
{
|
||||
UINT16 usAttackingWeapon = 0;
|
||||
INT32 sOrigGridNo = 0;
|
||||
BOOLEAN fFragment = FALSE;
|
||||
if (pBullet == NULL)
|
||||
{
|
||||
usAttackingWeapon = pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType;
|
||||
sOrigGridNo = pFirer->sGridNo;
|
||||
}
|
||||
else
|
||||
{
|
||||
usAttackingWeapon = pBullet->fromItem;
|
||||
sOrigGridNo = pBullet->sOrigGridNo;
|
||||
fFragment = pBullet->fFragment;
|
||||
}
|
||||
|
||||
INT32 iImpact, iFluke, iBonus, iImpactForCrits = 0;
|
||||
INT8 bStatLoss = 0;
|
||||
UINT8 ubAmmoType;
|
||||
@@ -8452,17 +8563,21 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
// in MoveBullet.
|
||||
|
||||
// Set a few things up:
|
||||
if ( Item[ pFirer->usAttackingWeapon ].usItemClass == IC_THROWING_KNIFE )
|
||||
if ( Item[ usAttackingWeapon ].usItemClass == IC_THROWING_KNIFE )
|
||||
{
|
||||
ubAmmoType = AMMO_KNIFE;
|
||||
}
|
||||
else
|
||||
// HEADROCK HAM 5: Added provisions for fragments, which are not fired from the weapon in your hand.
|
||||
else if ( fFragment == FALSE )
|
||||
{
|
||||
// Flugente: check for underbarrel weapons and use that object if necessary
|
||||
OBJECTTYPE* pObj = pFirer->GetUsedWeapon( &pFirer->inv[pFirer->ubAttackingHand] );
|
||||
|
||||
ubAmmoType = (*pObj)[0]->data.gun.ubGunAmmoType;
|
||||
}
|
||||
else
|
||||
{
|
||||
ubAmmoType = Explosive[Item[usAttackingWeapon].ubClassIndex].ubFragType;
|
||||
}
|
||||
|
||||
if ( TANK( pTarget ) )
|
||||
{
|
||||
@@ -8569,7 +8684,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
}
|
||||
|
||||
// Sniper trait adds bonus damage per aim click
|
||||
if (HAS_SKILL_TRAIT( pFirer, SNIPER_NT ) && (pFirer->aiData.bAimTime >= gSkillTraitValues.ubSNDamageBonusFromNumClicks))
|
||||
if (HAS_SKILL_TRAIT( pFirer, SNIPER_NT ) && (pFirer->aiData.bAimTime >= gSkillTraitValues.ubSNDamageBonusFromNumClicks) && !fFragment)
|
||||
{
|
||||
iImpact += (INT32)(iImpact * (pFirer->aiData.bAimTime - gSkillTraitValues.ubSNDamageBonusFromNumClicks + 1) * gSkillTraitValues.ubSNDamageBonusPerClick * NUM_SKILL_TRAITS( pFirer, SNIPER_NT ))/100; // +5% per trait
|
||||
}
|
||||
@@ -8593,8 +8708,15 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
else if (pTarget->ubSoldierClass == SOLDIER_CLASS_ELITE && gGameExternalOptions.sEnemyEliteDamageResistance != 0)
|
||||
iImpact -= ((iImpact * gGameExternalOptions.sEnemyEliteDamageResistance) /100);
|
||||
|
||||
|
||||
iImpact = max( 1, iImpact);
|
||||
// HEADROCK HAM 5.1: Oh sandro, you rendered zerominimumdamage moot...
|
||||
if ( AmmoTypes[ubAmmoType].zeroMinimumDamage )
|
||||
{
|
||||
iImpact = __max( 0, iImpact );
|
||||
}
|
||||
else
|
||||
{
|
||||
iImpact = __max( 1, iImpact);
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -8622,7 +8744,15 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
case MIKE:
|
||||
// Only 1/2 of the bonus
|
||||
iImpact -= (INT32)(iImpact * gGameExternalOptions.usSpecialNPCStronger / 200);
|
||||
iImpact = max( 1, iImpact);
|
||||
// HEADROCK HAM 5.1: Oh sandro, you rendered zerominimumdamage moot...
|
||||
if ( AmmoTypes[ubAmmoType].zeroMinimumDamage )
|
||||
{
|
||||
iImpact = __max( 0, iImpact );
|
||||
}
|
||||
else
|
||||
{
|
||||
iImpact = __max( 1, iImpact);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -8631,7 +8761,16 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// STOMP traits - Bodybuilding damage resistance
|
||||
if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pTarget, BODYBUILDING_NT ) )
|
||||
iImpact = max( 1, (INT32)(iImpact * (100 - gSkillTraitValues.ubBBDamageResistance) / 100));
|
||||
// HEADROCK HAM 5.1: Oh sandro, you rendered zerominimumdamage moot...
|
||||
if ( AmmoTypes[ubAmmoType].zeroMinimumDamage )
|
||||
{
|
||||
iImpact = __max( 0, (INT32)(iImpact * (100 - gSkillTraitValues.ubBBDamageResistance) / 100));
|
||||
}
|
||||
else
|
||||
{
|
||||
iImpact = __max( 1, (INT32)(iImpact * (100 - gSkillTraitValues.ubBBDamageResistance) / 100));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AdjustImpactByHitLocation( iImpact, ubHitLocation, &iImpact, &iImpactForCrits );
|
||||
@@ -8642,7 +8781,8 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
// is the blow deadly enough for an instant kill?
|
||||
// HEADROCK HAM 3.6: Reattached "Max Distance For Messy Death" tag from the XML! God knows why it wasn't attached when they MADE THAT TAG.
|
||||
//if ( PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= MAX_DISTANCE_FOR_MESSY_DEATH || (PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= MAX_BARRETT_DISTANCE_FOR_MESSY_DEATH && pFirer->usAttackingWeapon == BARRETT ))
|
||||
if ( PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= Weapon[ pFirer->usAttackingWeapon ].maxdistformessydeath )
|
||||
// HEADROCK HAM 5.1: Using usAttackingWeapon
|
||||
if ( PythSpacesAway( sOrigGridNo, pTarget->sGridNo ) <= Weapon[ usAttackingWeapon ].maxdistformessydeath )
|
||||
{
|
||||
if (iImpactForCrits > MIN_DAMAGE_FOR_INSTANT_KILL && iImpactForCrits < pTarget->stats.bLife)
|
||||
{
|
||||
@@ -8695,7 +8835,8 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
// since this value is much lower than the others, it only applies at short range...
|
||||
// HEADROCK HAM 3.6: Reattached "Max Distance For Messy Death" tag from the XML! God knows why it wasn't attached when they MADE THAT TAG.
|
||||
//if ( PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= MAX_DISTANCE_FOR_MESSY_DEATH || (PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= MAX_BARRETT_DISTANCE_FOR_MESSY_DEATH && pFirer->usAttackingWeapon == BARRETT ))
|
||||
if ( PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= Weapon[ pFirer->usAttackingWeapon ].maxdistformessydeath )
|
||||
// HEADROCK HAM 5.1: Using usAttackingWeapon
|
||||
if ( PythSpacesAway( sOrigGridNo, pTarget->sGridNo ) <= Weapon[ usAttackingWeapon ].maxdistformessydeath )
|
||||
{
|
||||
if (iImpact > MIN_DAMAGE_FOR_INSTANT_KILL && iImpact < pTarget->stats.bLife)
|
||||
{
|
||||
@@ -8741,7 +8882,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
if( !IsAutoResolveActive() )
|
||||
{
|
||||
|
||||
if ( AmmoTypes[ubAmmoType].knife && pFirer->aiData.bOppList[ pTarget->ubID ] == SEEN_CURRENTLY )
|
||||
if ( AmmoTypes[ubAmmoType].knife && pFirer->aiData.bOppList[ pTarget->ubID ] == SEEN_CURRENTLY && !fFragment )
|
||||
{
|
||||
// is this a stealth attack?
|
||||
if ( pTarget->aiData.bOppList[ pFirer->ubID ] == NOT_HEARD_OR_SEEN && !CREATURE_OR_BLOODCAT( pTarget )
|
||||
@@ -8793,10 +8934,18 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
|
||||
if (iImpactForCrits > 0 && iImpactForCrits < pTarget->stats.bLife && !(pTarget->flags.uiStatusFlags & SOLDIER_MONSTER) ) // not to monsters - SANDRO
|
||||
{
|
||||
UINT32 uiCritChance = (iImpactForCrits / 2) + (pFirer->aiData.bAimTime * 5);
|
||||
UINT32 uiCritChance = 0;
|
||||
if (fFragment)
|
||||
{
|
||||
uiCritChance = (iImpactForCrits / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiCritChance = (iImpactForCrits / 2) + (pFirer->aiData.bAimTime * 5);
|
||||
}
|
||||
BOOLEAN fMaliciousHit = FALSE;
|
||||
// SANDRO - Malicious characters inflict stat loss more often
|
||||
if ( gGameOptions.fNewTraitSystem && pFirer->ubProfile != NO_PROFILE )
|
||||
if ( gGameOptions.fNewTraitSystem && pFirer->ubProfile != NO_PROFILE && !fFragment)
|
||||
{
|
||||
if ( gMercProfiles[ pFirer->ubProfile ].bCharacterTrait == CHAR_TRAIT_MALICIOUS )
|
||||
{
|
||||
|
||||
+6
-1
@@ -358,6 +358,11 @@ typedef struct
|
||||
UINT16 ubDuration;
|
||||
UINT16 ubStartRadius;
|
||||
UINT8 ubMagSize;
|
||||
BOOLEAN fExplodeOnImpact; // HEADROCK HAM 5: Flag for impact explosives.
|
||||
UINT16 usNumFragments; // HEADROCK HAM 5.1: Fragmenting Explosive Data
|
||||
UINT8 ubFragType;
|
||||
UINT16 ubFragDamage;
|
||||
UINT16 ubFragRange;
|
||||
} EXPLOSIVETYPE;
|
||||
|
||||
//GLOBALS
|
||||
@@ -381,7 +386,7 @@ extern BOOLEAN FireWeapon( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo );
|
||||
extern void WeaponHit( UINT16 usSoldierID, UINT16 usWeaponIndex, INT16 sDamage, INT16 sBreathLoss, UINT16 usDirection, INT16 sXPos, INT16 sYPos, INT16 sZPos, INT16 sRange , UINT8 ubAttackerID, BOOLEAN fHit, UINT8 ubSpecial, UINT8 ubHitLocation );
|
||||
extern void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UINT8 ubAttackerID, UINT16 sXPos, INT16 sYPos, INT16 sZPos, UINT16 usStructureID, INT32 iImpact, BOOLEAN fStopped );
|
||||
extern void WindowHit( INT32 sGridNo, UINT16 usStructureID, BOOLEAN fBlowWindowSouth, BOOLEAN fLargeForce );
|
||||
extern INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 iImpact, INT16 sHitBy, UINT8 * pubSpecial );
|
||||
// HEADROCK HAM 5.1: Moved to Bullets.h
|
||||
extern BOOLEAN InRange( SOLDIERTYPE *pSoldier, INT32 sGridNo );
|
||||
extern void ShotMiss( UINT8 ubAttackerID, INT32 iBullet );
|
||||
extern UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, UINT8 ubAimPos );
|
||||
|
||||
@@ -60,6 +60,8 @@ typedef PARSE_STAGE;
|
||||
#define COMPATIBLEFACEITEMSFILENAME "CompatibleFaceItems.xml"
|
||||
#define MERGESFILENAME "Merges.xml"
|
||||
#define ATTACHMENTCOMBOMERGESFILENAME "AttachmentComboMerges.xml"
|
||||
// HEADROCK HAM 5: Item Transformations Filename
|
||||
#define ITEMTRANSFORMATIONSFILENAME "Item_Transformations.xml"
|
||||
#define MAGAZINESFILENAME "Magazines.xml"
|
||||
#define ARMOURSFILENAME "Armours.xml"
|
||||
#define EXPLOSIVESFILENAME "Explosives.xml"
|
||||
@@ -74,6 +76,9 @@ typedef PARSE_STAGE;
|
||||
// CHRISL:
|
||||
#define LOADBEARINGEQUIPMENTFILENAME "LoadBearingEquipment.xml"
|
||||
#define LBEPOCKETFILENAME "Pockets.xml"
|
||||
// THE_BOB : added for pocket popup definitions
|
||||
#define LBEPOCKETPOPUPFILENAME "PocketPopups.xml"
|
||||
|
||||
#define MERCSTARTINGGEARFILENAME "MercStartingGear.xml"
|
||||
|
||||
#ifdef JA2UB
|
||||
@@ -161,6 +166,8 @@ typedef PARSE_STAGE;
|
||||
#define FACILITYTYPESFILENAME "Map\\FacilityTypes.xml"
|
||||
// HEADROCK HAM 3.6: Sector Names [2009-07-27]
|
||||
#define SECTORNAMESFILENAME "Map\\SectorNames.xml"
|
||||
// HEADROCK HAM 5: Coolness by Sector [2011-11-19]
|
||||
#define COOLNESSBYSECTORFILENAME "Map\\CoolnessBySector.xml"
|
||||
// HEADROCK PROFEX: Merc Profiles [2009-07-27]
|
||||
#define MERCPROFILESFILENAME "MercProfiles.xml"
|
||||
// HEADROCK PROFEX: Merc Opinions [2009-07-27]
|
||||
@@ -267,6 +274,9 @@ extern BOOLEAN WriteMergeStats();
|
||||
extern BOOLEAN ReadInAttachmentComboMergeStats(STR fileName);
|
||||
extern BOOLEAN WriteAttachmentComboMergeStats();
|
||||
|
||||
// HEADROCK HAM 5: Item Transformation XML reader
|
||||
extern BOOLEAN ReadInTransformationStats(STR fileName);
|
||||
|
||||
extern BOOLEAN ReadInArmourStats(STR fileName);
|
||||
extern BOOLEAN WriteArmourStats();
|
||||
|
||||
@@ -277,6 +287,9 @@ extern BOOLEAN WritelbeEquipmentStats();
|
||||
extern BOOLEAN ReadInLBEPocketStats(STR fileName, BOOLEAN localizedVersion);
|
||||
extern BOOLEAN WriteLBEPocketEquipmentStats();
|
||||
|
||||
// THE_BOB : added for pocket popup definitions
|
||||
extern BOOLEAN ReadInLBEPocketPopups(STR fileName);
|
||||
|
||||
extern BOOLEAN ReadInMercStartingGearStats(STR fileName);
|
||||
extern BOOLEAN WriteMercStartingGearStats();
|
||||
|
||||
@@ -391,6 +404,9 @@ extern BOOLEAN ReadInFacilityTypes(STR fileName, BOOLEAN localizedVersion);
|
||||
// HEADROCK HAM 3.6: Customized Sector Names
|
||||
extern BOOLEAN ReadInSectorNames(STR fileName, BOOLEAN localizedVersion, INT8 Level );
|
||||
|
||||
// HEADROCK HAM 5: Coolness by Sectors
|
||||
extern BOOLEAN ReadInCoolnessBySector(STR fileName );
|
||||
|
||||
// HEADROCK PROFEX: Merc Profiles
|
||||
extern BOOLEAN ReadInMercProfiles(STR fileName, BOOLEAN localizedVersion);
|
||||
|
||||
|
||||
@@ -57,7 +57,12 @@ explosiveStartElementHandle(void *userData, const XML_Char *name, const XML_Char
|
||||
strcmp(name, "ubStartRadius") == 0 ||
|
||||
strcmp(name, "ubMagSize") == 0 ||
|
||||
strcmp(name, "ubDuration") == 0 ||
|
||||
strcmp(name, "ubAnimationID") == 0 ))
|
||||
strcmp(name, "ubAnimationID") == 0 ||
|
||||
strcmp(name, "fExplodeOnImpact") == 0 ||// HEADROCK HAM 5: Explode on impact flag
|
||||
strcmp(name, "usNumFragments") == 0 || // HEADROCK HAM 5.1: Fragmenting explosive data
|
||||
strcmp(name, "ubFragType") == 0 ||
|
||||
strcmp(name, "ubFragDamage") == 0 ||
|
||||
strcmp(name, "ubFragRange") == 0 ))
|
||||
{
|
||||
pData->curElement = ELEMENT_PROPERTY;
|
||||
|
||||
@@ -159,6 +164,37 @@ explosiveEndElementHandle(void *userData, const XML_Char *name)
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curExplosive.ubDuration = (UINT8) atol(pData->szCharData);
|
||||
}
|
||||
// HEADROCK HAM 5: Flag for "Explosion on Impact"
|
||||
else if(strcmp(name, "fExplodeOnImpact") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curExplosive.fExplodeOnImpact = (BOOLEAN) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
// HEADROCK HAM 5.1: Four tags for Fragmenting Explosives
|
||||
else if(strcmp(name, "usNumFragments") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curExplosive.usNumFragments = (UINT16) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "ubFragType") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curExplosive.ubFragType = (UINT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "ubFragDamage") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curExplosive.ubFragDamage = (UINT16) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "ubFragRange") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curExplosive.ubFragRange = (UINT16) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
@@ -262,6 +298,7 @@ BOOLEAN WriteExplosiveStats()
|
||||
FilePrintf(hFile,"\t\t<ubDuration>%d</ubDuration>\r\n", Explosive[cnt].ubDuration );
|
||||
FilePrintf(hFile,"\t\t<ubStartRadius>%d</ubStartRadius>\r\n", Explosive[cnt].ubStartRadius );
|
||||
FilePrintf(hFile,"\t\t<ubMagSize>%d</ubMagSize>\r\n", Explosive[cnt].ubMagSize );
|
||||
FilePrintf(hFile,"\t\t<fExplodeOnImpact>%d</fExplodeOnImpact>\r\n", (UINT8)Explosive[cnt].fExplodeOnImpact );
|
||||
|
||||
FilePrintf(hFile,"\t</EXPLOSIVE>\r\n");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
#ifdef PRECOMPILEDHEADERS
|
||||
#include "Tactical All.h"
|
||||
#else
|
||||
#include "sgp.h"
|
||||
#include "overhead.h"
|
||||
#include "weapons.h"
|
||||
#include "Debug Control.h"
|
||||
#include "expat.h"
|
||||
#include "gamesettings.h"
|
||||
#include "XML.h"
|
||||
#include "Item Types.h"
|
||||
#endif
|
||||
|
||||
struct
|
||||
{
|
||||
PARSE_STAGE curElement;
|
||||
|
||||
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
|
||||
|
||||
TransformInfoStruct curTransform;
|
||||
UINT32 maxArraySize;
|
||||
UINT32 curIndex;
|
||||
UINT32 curResultIndex;
|
||||
UINT32 currentDepth;
|
||||
UINT32 maxReadDepth;
|
||||
}
|
||||
typedef transformParseData;
|
||||
|
||||
static void XMLCALL
|
||||
transformStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
transformParseData * pData = (transformParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
|
||||
{
|
||||
if(strcmp(name, "TRANSFORMATIONS_LIST") == 0 && pData->curElement == ELEMENT_NONE)
|
||||
{
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
// Reset all transformation indexes to -1, indicating they are "Not Taken"
|
||||
for (UINT16 x = 0; x < MAXITEMS; x++)
|
||||
{
|
||||
Transform[x].usItem = -1;
|
||||
}
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(strcmp(name, "TRANSFORM") == 0 && pData->curElement == ELEMENT_LIST)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
// Reset values
|
||||
pData->curTransform.usItem = -1;
|
||||
for (UINT8 x = 0; x < MAX_NUM_TRANSFORMATION_RESULTS; x++)
|
||||
{
|
||||
pData->curTransform.usResult[x] = 0;
|
||||
}
|
||||
pData->curTransform.usAPCost = 0;
|
||||
swprintf(pData->curTransform.szMenuRowText, L"");
|
||||
swprintf(pData->curTransform.szTooltipText, L"");
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
pData->curIndex++;
|
||||
pData->curResultIndex = 0;
|
||||
}
|
||||
else if(pData->curElement == ELEMENT &&
|
||||
(strcmp(name, "usItem") == 0 ||
|
||||
strcmp(name, "usResult") == 0 ||
|
||||
strcmp(name, "usAPCost") == 0 ||
|
||||
strcmp(name, "iBPCost") == 0 ||
|
||||
strcmp(name, "szMenuRowText") == 0 ||
|
||||
strcmp(name, "szTooltipText") == 0))
|
||||
{
|
||||
pData->curElement = ELEMENT_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
pData->szCharData[0] = '\0';
|
||||
}
|
||||
|
||||
pData->currentDepth++;
|
||||
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
transformCharacterDataHandle(void *userData, const XML_Char *str, int len)
|
||||
{
|
||||
transformParseData * pData = (transformParseData *)userData;
|
||||
|
||||
if( (pData->currentDepth <= pData->maxReadDepth) &&
|
||||
(strlen(pData->szCharData) < MAX_CHAR_DATA_LENGTH)
|
||||
){
|
||||
strncat(pData->szCharData,str,__min((unsigned int)len,MAX_CHAR_DATA_LENGTH-strlen(pData->szCharData)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void XMLCALL
|
||||
transformEndElementHandle(void *userData, const XML_Char *name)
|
||||
{
|
||||
transformParseData * pData = (transformParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
|
||||
{
|
||||
if(strcmp(name, "TRANSFORMATIONS_LIST") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT_NONE;
|
||||
}
|
||||
else if(strcmp(name, "TRANSFORM") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
if(pData->curIndex < pData->maxArraySize)
|
||||
{
|
||||
//DebugMsg(TOPIC_JA2, DBG_LEVEL_3,"MergeStartElementHandle: writing merge to array");
|
||||
Transform[pData->curIndex].usItem = pData->curTransform.usItem; //write the merge into the table
|
||||
for (INT32 x = 0; x < MAX_NUM_TRANSFORMATION_RESULTS; x++)
|
||||
{
|
||||
Transform[pData->curIndex].usResult[x] = pData->curTransform.usResult[x];
|
||||
}
|
||||
Transform[pData->curIndex].usAPCost = pData->curTransform.usAPCost;
|
||||
Transform[pData->curIndex].iBPCost = pData->curTransform.iBPCost;
|
||||
wcscpy( Transform[pData->curIndex].szMenuRowText, pData->curTransform.szMenuRowText );
|
||||
wcscpy( Transform[pData->curIndex].szTooltipText, pData->curTransform.szTooltipText );
|
||||
}
|
||||
}
|
||||
else if(strcmp(name, "usItem") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
INT16 usItem = (INT16) atol(pData->szCharData);
|
||||
if (usItem <= 0)
|
||||
{
|
||||
AssertMsg( 0, String( "Item_Transformations.XML error: Entry #%d missing proper <usItem> tag!", pData->curIndex ) );
|
||||
}
|
||||
pData->curTransform.usItem = usItem;
|
||||
}
|
||||
else if(strcmp(name, "usResult") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curTransform.usResult[pData->curResultIndex] = (UINT16) atol(pData->szCharData);
|
||||
pData->curResultIndex++;
|
||||
}
|
||||
else if(strcmp(name, "usAPCost") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curTransform.usAPCost = (UINT16) atol(pData->szCharData);
|
||||
pData->curTransform.usAPCost = (UINT16)DynamicAdjustAPConstants(pData->curTransform.usAPCost, pData->curTransform.usAPCost);
|
||||
}
|
||||
else if(strcmp(name, "iBPCost") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curTransform.iBPCost = (INT32) atol(pData->szCharData);
|
||||
}
|
||||
else if(strcmp(name, "szMenuRowText") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curTransform.szMenuRowText, sizeof(pData->curTransform.szMenuRowText)/sizeof(pData->curTransform.szMenuRowText[0]) );
|
||||
pData->curTransform.szMenuRowText[sizeof(pData->curTransform.szMenuRowText)/sizeof(pData->curTransform.szMenuRowText[0]) - 1] = '\0';
|
||||
}
|
||||
else if(strcmp(name, "szTooltipText") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curTransform.szTooltipText, sizeof(pData->curTransform.szTooltipText)/sizeof(pData->curTransform.szTooltipText[0]) );
|
||||
pData->curTransform.szTooltipText[sizeof(pData->curTransform.szTooltipText)/sizeof(pData->curTransform.szTooltipText[0]) - 1] = '\0';
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
|
||||
pData->currentDepth--;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
BOOLEAN ReadInTransformationStats(STR fileName)
|
||||
{
|
||||
HWFILE hFile;
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8 * lpcBuffer;
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
transformParseData pData;
|
||||
|
||||
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Loading Item_Transformations.xml" );
|
||||
|
||||
// Open merges file
|
||||
hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE );
|
||||
if ( !hFile )
|
||||
return( FALSE );
|
||||
|
||||
uiFSize = FileGetSize(hFile);
|
||||
lpcBuffer = (CHAR8 *) MemAlloc(uiFSize+1);
|
||||
|
||||
//Read in block
|
||||
if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) )
|
||||
{
|
||||
MemFree(lpcBuffer);
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
lpcBuffer[uiFSize] = 0; //add a null terminator
|
||||
|
||||
FileClose( hFile );
|
||||
|
||||
|
||||
XML_SetElementHandler(parser, transformStartElementHandle, transformEndElementHandle);
|
||||
XML_SetCharacterDataHandler(parser, transformCharacterDataHandle);
|
||||
|
||||
|
||||
memset(&pData,0,sizeof(pData));
|
||||
pData.maxArraySize = MAXITEMS;
|
||||
pData.curIndex = -1;
|
||||
|
||||
XML_SetUserData(parser, &pData);
|
||||
|
||||
|
||||
if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE))
|
||||
{
|
||||
CHAR8 errorBuf[511];
|
||||
|
||||
sprintf(errorBuf, "XML Parser Error in Item_Transformations.xml: %s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
|
||||
LiveMessage(errorBuf);
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
|
||||
|
||||
XML_ParserFree(parser);
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,496 @@
|
||||
#ifdef PRECOMPILEDHEADERS
|
||||
#include "Tactical All.h"
|
||||
#else
|
||||
#include "sgp.h"
|
||||
#include "popup_class.h"
|
||||
#include "popup_definition.h"
|
||||
#include "Debug Control.h"
|
||||
#include "expat.h"
|
||||
#include "XML.h"
|
||||
#include "GameSettings.h"
|
||||
#endif
|
||||
|
||||
// namespace'd because of name collision with POPUP class def
|
||||
namespace POPUP_PARSE {
|
||||
enum
|
||||
{
|
||||
OUTSIDE_POCKET_LIST = 0,
|
||||
POCKET_LIST,
|
||||
|
||||
POCKET,
|
||||
POCKET_PROPERTY, // for reading pocket id
|
||||
|
||||
POPUP,
|
||||
POPUP_PROPERTY, // unused
|
||||
// for root-level popup
|
||||
OPTION,
|
||||
OPTION_PROPERTY,
|
||||
GENERATOR,
|
||||
GENERATOR_PROPERTY,
|
||||
|
||||
SUBMENU,
|
||||
SUBMENU_PROPERTY,
|
||||
// for submenus
|
||||
SUBMENU_OPTION,
|
||||
SUBMENU_OPTION_PROPERTY,
|
||||
SUBMENU_GENERATOR,
|
||||
SUBMENU_GENERATOR_PROPERTY
|
||||
}
|
||||
typedef POPUP_PARSE_STAGE;
|
||||
}
|
||||
|
||||
|
||||
struct
|
||||
{
|
||||
POPUP_PARSE::POPUP_PARSE_STAGE curElement;
|
||||
UINT8 curSubPopupLevel;
|
||||
|
||||
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
|
||||
|
||||
// popupDef and its pocket number
|
||||
UINT8 curPocketId;
|
||||
popupDef *curPocketPopup;
|
||||
|
||||
// for reading in options to popups and subPopups
|
||||
//popupDefOption *curPocketPopupOption; // not really used
|
||||
WCHAR curPocketPopupOptionName[128];
|
||||
UINT16 curPocketPopupOptionCallback;
|
||||
UINT16 curPocketPopupOptionAvail;
|
||||
|
||||
// for reading in subPopups
|
||||
popupDefSubPopupOption *curPocketSubPopupOption[POPUP_MAX_SUB_POPUPS];
|
||||
WCHAR curPocketSubPopupOptionName[POPUP_MAX_SUB_POPUPS][128];
|
||||
|
||||
// for reading in content generator references
|
||||
popupDefContentGenerator *curPocketPopupGenerator; // not really used
|
||||
UINT16 curPocketPopupGeneratorId;
|
||||
|
||||
popupDef * curArray;
|
||||
|
||||
UINT32 maxArraySize;
|
||||
UINT32 curIndex;
|
||||
UINT32 currentDepth;
|
||||
UINT32 maxReadDepth;
|
||||
}
|
||||
typedef pocketPopupParseData;
|
||||
|
||||
// maps generator name strings found in XML to generator IDs used by the function that binds them
|
||||
static UINT16 mapGeneratorNameToId( CHAR8 * name ){
|
||||
|
||||
if( strcmp(name,"dummy") == 0 ){
|
||||
return popupGenerators::dummy;
|
||||
} else if( strcmp(name,"addArmor") == 0 ){
|
||||
return popupGenerators::addArmor;
|
||||
} else if( strcmp(name,"addLBE") == 0 ){
|
||||
return popupGenerators::addLBE;
|
||||
} else if( strcmp(name,"addWeapons") == 0 ){
|
||||
return popupGenerators::addWeapons;
|
||||
} else if( strcmp(name,"addWeaponGroups") == 0 ){
|
||||
return popupGenerators::addWeaponGroups;
|
||||
} else if( strcmp(name,"addGrenades") == 0 ){
|
||||
return popupGenerators::addGrenades;
|
||||
} else if( strcmp(name,"addBombs") == 0 ){
|
||||
return popupGenerators::addBombs;
|
||||
} else if( strcmp(name,"addFaceGear") == 0 ){
|
||||
return popupGenerators::addFaceGear;
|
||||
} else if( strcmp(name,"addAmmo") == 0 ){
|
||||
return popupGenerators::addAmmo;
|
||||
} else if( strcmp(name,"addRifleGrenades") == 0 ){
|
||||
return popupGenerators::addRifleGrenades;
|
||||
} else if( strcmp(name,"addRocketAmmo") == 0 ){
|
||||
return popupGenerators::addRocketAmmo;
|
||||
} else if( strcmp(name,"addMisc") == 0 ){
|
||||
return popupGenerators::addMisc;
|
||||
} else if( strcmp(name,"addKits") == 0 ){
|
||||
return popupGenerators::addKits;
|
||||
} else return 0; // includes 'none'
|
||||
|
||||
}
|
||||
|
||||
// maps option callback name strings found in XML to callback IDs used by the function that binds them
|
||||
static UINT16 mapCallbackNameToId( CHAR8 * name ){
|
||||
|
||||
if( strcmp(name,"dummy") == 0 ){
|
||||
return 1;
|
||||
} else return 0; // includes 'none'
|
||||
|
||||
}
|
||||
|
||||
// maps option availability check function name strings found in XML to their IDs used by the function that binds them
|
||||
static UINT16 mapAvailNameToId( CHAR8 * name ){
|
||||
|
||||
if( strcmp(name,"dummy") == 0 ){
|
||||
return 1;
|
||||
} else return 0; // includes 'none'
|
||||
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
pocketPopupStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
pocketPopupParseData * pData = (pocketPopupParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
|
||||
{
|
||||
if(strcmp(name, "POCKETPOPUPS") == 0 && pData->curElement == ELEMENT_NONE)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POCKET_LIST;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(strcmp(name, "POCKET") == 0 && pData->curElement == ELEMENT_LIST)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POCKET;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
// TODO: assert if there's no dangling subpopup here, broken XML might cause trouble
|
||||
pData->curSubPopupLevel = 0; // we're in a new pocket now, so reset the subpopup level
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::POCKET &&
|
||||
(strcmp(name, "pIndex") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POCKET_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::POCKET &&
|
||||
(strcmp(name, "popup") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POPUP;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
pData->curPocketPopup = new popupDef();
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::POPUP && // popup options (not in submenu)
|
||||
(strcmp(name, "option") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::OPTION;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::OPTION && // popup option attributes (not in submenu)
|
||||
( strcmp(name, "name") == 0
|
||||
|| strcmp(name, "action") == 0
|
||||
|| strcmp(name, "availCheck") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::OPTION_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::POPUP && // content generators (not in submenu)
|
||||
(strcmp(name, "generator") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::GENERATOR;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::GENERATOR && // content generator attributes (not in submenu)
|
||||
( strcmp(name, "id") == 0 ) )
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::GENERATOR_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::POPUP && // submenu (first)
|
||||
(strcmp(name, "subMenu") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU;
|
||||
|
||||
// TODO: assert that this is the first submenu
|
||||
pData->curSubPopupLevel = 1; // we're still at popup level so this must be the first subpopup
|
||||
pData->curPocketSubPopupOption[ pData->curSubPopupLevel-1 ] = new popupDefSubPopupOption();
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::SUBMENU && // submenu (deep)
|
||||
(strcmp(name, "subMenu") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU;
|
||||
|
||||
pData->curSubPopupLevel++;
|
||||
pData->curPocketSubPopupOption[ pData->curSubPopupLevel-1 ] = new popupDefSubPopupOption();
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::SUBMENU && // submenu attributes
|
||||
( strcmp(name, "name") == 0 ) )
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::SUBMENU && // popup options (submenu)
|
||||
(strcmp(name, "option") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_OPTION;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::SUBMENU_OPTION && // popup option attributes (submenu)
|
||||
( strcmp(name, "name") == 0
|
||||
|| strcmp(name, "action") == 0
|
||||
|| strcmp(name, "availCheck") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_OPTION_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::SUBMENU && // content generators (submenu)
|
||||
(strcmp(name, "generator") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_GENERATOR;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::SUBMENU_GENERATOR && // content generator attributes (submenu)
|
||||
( strcmp(name, "id") == 0 ) )
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_GENERATOR_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
|
||||
pData->szCharData[0] = '\0';
|
||||
}
|
||||
|
||||
pData->currentDepth++;
|
||||
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
pocketPopupCharacterDataHandle(void *userData, const XML_Char *str, int len)
|
||||
{
|
||||
pocketPopupParseData * pData = (pocketPopupParseData *)userData;
|
||||
|
||||
if( (pData->currentDepth <= pData->maxReadDepth) &&
|
||||
(strlen(pData->szCharData) < MAX_CHAR_DATA_LENGTH)
|
||||
){
|
||||
strncat(pData->szCharData,str,__min((unsigned int)len,MAX_CHAR_DATA_LENGTH-strlen(pData->szCharData)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void XMLCALL
|
||||
pocketPopupEndElementHandle(void *userData, const XML_Char *name)
|
||||
{
|
||||
pocketPopupParseData * pData = (pocketPopupParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth)
|
||||
{
|
||||
if(strcmp(name, "POCKETPOPUPS") == 0)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::OUTSIDE_POCKET_LIST;
|
||||
}
|
||||
else if(strcmp(name, "POCKET") == 0)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POCKET_LIST;
|
||||
|
||||
// done with the pocket
|
||||
// nothing to do because we already saved the popup when closing <popup> tag
|
||||
|
||||
}
|
||||
else if(strcmp(name, "pIndex") == 0)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POCKET;
|
||||
pData->curPocketId = (UINT8) atol(pData->szCharData); // got pocket index
|
||||
}
|
||||
else if(strcmp(name, "popup") == 0)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POCKET;
|
||||
// done with the popup definition
|
||||
LBEPocketPopup[ pData->curPocketId ] = *pData->curPocketPopup; // place the popup definition in pocket popup index
|
||||
}
|
||||
else if(strcmp(name, "subMenu") == 0)
|
||||
{
|
||||
|
||||
// done with the subpopup definition
|
||||
|
||||
// rename the current option, we should've collected a name for it by now
|
||||
pData->curPocketSubPopupOption[ pData->curSubPopupLevel-1 ]->rename( new std::wstring( pData->curPocketSubPopupOptionName[ pData->curSubPopupLevel-1 ] ) );
|
||||
|
||||
if( pData->curSubPopupLevel == 1 ){ // at first submenu level, add the current menu to the base popup
|
||||
pData->curElement = POPUP_PARSE::POPUP;
|
||||
|
||||
pData->curPocketPopup->addSubPopup( pData->curPocketSubPopupOption[ pData->curSubPopupLevel-1 ] );
|
||||
pData->curSubPopupLevel = 0;
|
||||
} else { // deep in submenu tree, add the current submenu to the one above
|
||||
pData->curElement = POPUP_PARSE::SUBMENU;
|
||||
|
||||
pData->curPocketSubPopupOption[ pData->curSubPopupLevel - 2 ]->getSubDef()->addSubPopup( pData->curPocketSubPopupOption[ pData->curSubPopupLevel-1 ] );
|
||||
pData->curSubPopupLevel--;
|
||||
}
|
||||
|
||||
}
|
||||
else if( pData->curElement == POPUP_PARSE::OPTION && strcmp(name, "option") == 0) // option (popup)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POPUP;
|
||||
// done with the option
|
||||
pData->curPocketPopup->addOption( new std::wstring( pData->curPocketPopupOptionName ), pData->curPocketPopupOptionCallback, pData->curPocketPopupOptionAvail );
|
||||
}
|
||||
else if( pData->curElement == POPUP_PARSE::SUBMENU_OPTION && strcmp(name, "option") == 0) // option (sub-popup)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU;
|
||||
// done with the option
|
||||
pData->curPocketSubPopupOption[ pData->curSubPopupLevel-1 ]->getSubDef()->addOption( new std::wstring( pData->curPocketPopupOptionName ), pData->curPocketPopupOptionCallback, pData->curPocketPopupOptionAvail );
|
||||
}
|
||||
else if( pData->curElement == POPUP_PARSE::GENERATOR && strcmp(name, "generator") == 0) // generator (popup)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POPUP;
|
||||
// done with the generator
|
||||
pData->curPocketPopup->addGenerator( pData->curPocketPopupGeneratorId );
|
||||
}
|
||||
else if( pData->curElement == POPUP_PARSE::SUBMENU_GENERATOR && strcmp(name, "generator") == 0) // generator (sub-popup)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU;
|
||||
// done with the generator
|
||||
pData->curPocketSubPopupOption[ pData->curSubPopupLevel-1 ]->getSubDef()->addGenerator( pData->curPocketPopupGeneratorId );
|
||||
}
|
||||
else if(strcmp(name, "name") == 0)
|
||||
{
|
||||
switch( pData->curElement ){
|
||||
case POPUP_PARSE::OPTION_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::OPTION;
|
||||
|
||||
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curPocketPopupOptionName, sizeof(pData->curPocketPopupOptionName)/sizeof(pData->curPocketPopupOptionName[0]) );
|
||||
pData->curPocketPopupOptionName[sizeof(pData->curPocketPopupOptionName)/sizeof(pData->curPocketPopupOptionName[0]) - 1] = '\0';
|
||||
|
||||
break;
|
||||
|
||||
case POPUP_PARSE::SUBMENU_OPTION_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_OPTION;
|
||||
|
||||
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curPocketPopupOptionName, sizeof(pData->curPocketPopupOptionName)/sizeof(pData->curPocketPopupOptionName[0]) );
|
||||
pData->curPocketPopupOptionName[sizeof(pData->curPocketPopupOptionName)/sizeof(pData->curPocketPopupOptionName[0]) - 1] = '\0';
|
||||
|
||||
break;
|
||||
|
||||
case POPUP_PARSE::SUBMENU_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::SUBMENU;
|
||||
|
||||
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curPocketSubPopupOptionName[pData->curSubPopupLevel-1], sizeof(pData->curPocketSubPopupOptionName[pData->curSubPopupLevel-1])/sizeof(pData->curPocketSubPopupOptionName[pData->curSubPopupLevel-1][0]) );
|
||||
pData->curPocketSubPopupOptionName[pData->curSubPopupLevel-1][sizeof(pData->curPocketSubPopupOptionName[pData->curSubPopupLevel-1])/sizeof(pData->curPocketSubPopupOptionName[pData->curSubPopupLevel-1][0]) - 1] = '\0';
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
else if(strcmp(name, "action") == 0)
|
||||
{
|
||||
switch( pData->curElement ){
|
||||
case POPUP_PARSE::OPTION_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::OPTION;
|
||||
break;
|
||||
|
||||
case POPUP_PARSE::SUBMENU_OPTION_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_OPTION;
|
||||
break;
|
||||
}
|
||||
|
||||
pData->curPocketPopupOptionCallback = mapCallbackNameToId(pData->szCharData);
|
||||
}
|
||||
else if(strcmp(name, "availCheck") == 0)
|
||||
{
|
||||
switch( pData->curElement ){
|
||||
case POPUP_PARSE::OPTION_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::OPTION;
|
||||
break;
|
||||
|
||||
case POPUP_PARSE::SUBMENU_OPTION_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_OPTION;
|
||||
break;
|
||||
}
|
||||
|
||||
pData->curPocketPopupOptionAvail = mapAvailNameToId(pData->szCharData);
|
||||
}
|
||||
else if(strcmp(name, "id") == 0)
|
||||
{
|
||||
switch( pData->curElement ){
|
||||
case POPUP_PARSE::GENERATOR_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::GENERATOR;
|
||||
break;
|
||||
|
||||
case POPUP_PARSE::SUBMENU_GENERATOR_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_GENERATOR;
|
||||
break;
|
||||
}
|
||||
|
||||
pData->curPocketPopupGeneratorId = mapGeneratorNameToId(pData->szCharData);
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
pData->currentDepth--;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN ReadInLBEPocketPopups(STR fileName)
|
||||
{
|
||||
HWFILE hFile;
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8 * lpcBuffer;
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
pocketPopupParseData pData;
|
||||
|
||||
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Loading pocketPopups.xml" );
|
||||
|
||||
hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE );
|
||||
if ( !hFile )
|
||||
return( FALSE );
|
||||
|
||||
uiFSize = FileGetSize(hFile);
|
||||
lpcBuffer = (CHAR8 *) MemAlloc(uiFSize+1);
|
||||
|
||||
//Read in block
|
||||
if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) )
|
||||
{
|
||||
MemFree(lpcBuffer);
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
lpcBuffer[uiFSize] = 0; //add a null terminator
|
||||
|
||||
FileClose( hFile );
|
||||
|
||||
|
||||
XML_SetElementHandler(parser, pocketPopupStartElementHandle, pocketPopupEndElementHandle);
|
||||
XML_SetCharacterDataHandler(parser, pocketPopupCharacterDataHandle);
|
||||
|
||||
|
||||
memset(&pData,0,sizeof(pData));
|
||||
XML_SetUserData(parser, &pData);
|
||||
|
||||
XML_SetUserData(parser, &pData);
|
||||
|
||||
if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE))
|
||||
{
|
||||
CHAR8 errorBuf[511];
|
||||
|
||||
sprintf(errorBuf, "XML Parser Error in Pocket.xml: %s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
|
||||
LiveMessage(errorBuf);
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
// dummy popup
|
||||
|
||||
popupDef* popup = new popupDef();
|
||||
popup->addOption(new std::wstring(L"Option one"),NULL,NULL);
|
||||
popup->addOption(new std::wstring(L"Option two"),NULL,NULL);
|
||||
popup->addOption(new std::wstring(L"Option three"),NULL,NULL);
|
||||
|
||||
LBEPocketPopup[5] = *popup;
|
||||
*/
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
|
||||
|
||||
XML_ParserFree(parser);
|
||||
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
+17
-5
@@ -31,7 +31,8 @@
|
||||
#endif
|
||||
|
||||
// Defines
|
||||
#define NUM_BULLET_SLOTS 50
|
||||
// HEADROCK HAM 5: Increasing... with the hope of making spectacular fragmenting explosives.
|
||||
#define NUM_BULLET_SLOTS 200
|
||||
|
||||
|
||||
// GLOBAL FOR FACES LISTING
|
||||
@@ -105,7 +106,11 @@ INT32 CreateBullet( UINT8 ubFirerID, BOOLEAN fFake, UINT16 usFlags,UINT16 fromIt
|
||||
{
|
||||
pBullet->fReal = TRUE;
|
||||
// gBullets[ iBullet ].pFirer->bBulletsLeft++;
|
||||
gTacticalStatus.ubAttackBusyCount++;
|
||||
// HEADROCK HAM 5: Do not create for explosives.
|
||||
if (!(Item[fromItem].usItemClass & IC_EXPLOSV))
|
||||
{
|
||||
gTacticalStatus.ubAttackBusyCount++;
|
||||
}
|
||||
DebugAttackBusy( String( "Creating a new bullet for %d. ABC now %d\n", ubFirerID, gTacticalStatus.ubAttackBusyCount) );
|
||||
}
|
||||
|
||||
@@ -201,7 +206,11 @@ void RemoveBullet( INT32 iBullet )
|
||||
// DebugAttackBusy( String( "Deleting a bullet for %d. Total count now %d\n", gBullets[ iBullet].ubFirerID, gBullets[ iBullet ].pFirer->bBulletsLeft) );
|
||||
// Nah, just decrement the attack busy count and be done with it
|
||||
DebugAttackBusy( String( "Deleting a bullet for %d.\n", gBullets[ iBullet].ubFirerID ) );
|
||||
ReduceAttackBusyCount( );
|
||||
// HEADROCK HAM 5: Fragments do not need reducing.
|
||||
if (gBullets[iBullet].fFragment == false)
|
||||
{
|
||||
ReduceAttackBusyCount( );
|
||||
}
|
||||
|
||||
// if ( gBullets[ iBullet ].usFlags & ( BULLET_FLAG_KNIFE ) )
|
||||
// {
|
||||
@@ -233,7 +242,8 @@ void RemoveBullet( INT32 iBullet )
|
||||
|
||||
void LocateBullet( INT32 iBulletIndex )
|
||||
{
|
||||
if ( gGameSettings.fOptions[ TOPTION_SHOW_MISSES ] )
|
||||
// HEADROCK HAM 5: Do not track fragments. There are too many of them.
|
||||
if ( gGameSettings.fOptions[ TOPTION_SHOW_MISSES ] && gBullets[ iBulletIndex ].fFragment == false)
|
||||
{
|
||||
// Check if a bad guy fired!
|
||||
if ( gBullets[ iBulletIndex ].ubFirerID != NOBODY )
|
||||
@@ -353,6 +363,7 @@ void UpdateBullets( )
|
||||
ManLooksForOtherTeams(gBullets[ uiCount ].pFirer);
|
||||
}
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
pNode = AddStructToTail( gBullets[ uiCount ].sGridNo, BULLETTILE1 );
|
||||
@@ -364,7 +375,8 @@ void UpdateBullets( )
|
||||
pNode->sRelativeZ = (INT16) CONVERT_HEIGHTUNITS_TO_PIXELS( FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrZ ) );
|
||||
|
||||
//afp-start - add new tail /tracer
|
||||
if (gGameSettings.fOptions[TOPTION_ALTERNATE_BULLET_GRAPHICS])
|
||||
// HEADROCK HAM 5: No tail for fragments.
|
||||
if (gGameSettings.fOptions[TOPTION_ALTERNATE_BULLET_GRAPHICS] && gBullets[ uiCount ].fFragment == false)
|
||||
{
|
||||
if ((lastX != 0) || (lastY != 0))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user