Added: Ctrl+Shift+E now fill LBE items in sector with other items and places them in vehicles first.

Added: Right-Click on remove attachments button on sector inventory screen will not empty LBE items in sector
Changed: SLAY_STAYS_FOREVER disables Slay's hourly chance to leave when unattended
Added: SLAY_HOURLY_CHANCE_TO_LEAVE setting to Ja2_Options.ini
Fixed: a bunch of array index out of bounds bugs
Fixed: a bunch of typos in if contitions
Fixed: BuildListFile() function loading items from index 1 instead 0
Added translation: Polish text for some map inventory screen items
Added translation: English texts for new functionality for other language files
Cleaned up some old TODOs

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8404 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
TheBob
2017-05-19 13:40:34 +00:00
parent dc350d724d
commit b60a94afc5
39 changed files with 565 additions and 146 deletions
+4 -2
View File
@@ -589,8 +589,10 @@ UINT16 DetermineCivQuoteEntry( SOLDIERTYPE *pCiv, UINT16 *pubCivHintToUse, BOOLE
// Determine what type of quote to say...
// Are are we going to attack?
if ( pCiv->aiData.bAction == AI_ACTION_TOSS_PROJECTILE || pCiv->aiData.bAction == AI_ACTION_FIRE_GUN ||
pCiv->aiData.bAction == AI_ACTION_FIRE_GUN || pCiv->aiData.bAction == AI_ACTION_KNIFE_MOVE )
if ( pCiv->aiData.bAction == AI_ACTION_TOSS_PROJECTILE
|| pCiv->aiData.bAction == AI_ACTION_FIRE_GUN
|| pCiv->aiData.bAction == AI_ACTION_THROW_KNIFE
|| pCiv->aiData.bAction == AI_ACTION_KNIFE_MOVE )
{
return( CIV_QUOTE_ENEMY_THREAT );
}
+5 -5
View File
@@ -11002,7 +11002,7 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
else
{
SetFontForeground( 5 );
swprintf( pStr, L"=", iFloatModifier[cnt2] );
swprintf( pStr, L"=" );
}
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
}
@@ -12016,25 +12016,25 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
if (iModifier[cnt2])
{
SetFontForeground( 5 );
swprintf( pStr, L"=", iModifier[cnt2] );
swprintf( pStr, L"=" );
}
else
{
SetFontForeground( ITEMDESC_FONTPOSITIVE );
swprintf( pStr, L"Y", iModifier[cnt2] );
swprintf( pStr, L"Y" );
}
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
}
else if ( fComparisonMode && !iComparedModifier[0] )
{
SetFontForeground( ITEMDESC_FONTNEGATIVE );
swprintf( pStr, L"N", iModifier[cnt2] );
swprintf( pStr, L"N" );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
}
else if (iModifier[cnt2])
{
SetFontForeground( ITEMDESC_FONTPOSITIVE );
swprintf( pStr, L"Y", iModifier[cnt2] ); // FIXME: unused param
swprintf( pStr, L"Y" );
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY);
}
else
+15 -11
View File
@@ -156,10 +156,10 @@ void CreateLBE (OBJECTTYPE* pObj, UINT8 ubID, int numSubPockets)
(*pObj)[0]->data.lbe.uniqueID = uniqueID;
}
bool DestroyLBEIfEmpty(OBJECTTYPE* pObj)
bool DestroyLBEIfEmpty(OBJECTTYPE* pObj, int stackIndex)
{
if (pObj->IsActiveLBE(0) == true) {
LBENODE* pLBE = pObj->GetLBEPointer(0);
if (pObj->IsActiveLBE(stackIndex) == true) {
LBENODE* pLBE = pObj->GetLBEPointer(stackIndex);
if (pLBE)
{
UINT16 plbesize = pLBE->inv.size();
@@ -174,19 +174,19 @@ bool DestroyLBEIfEmpty(OBJECTTYPE* pObj)
break;
}
}
(*pObj)[0]->data.lbe.uniqueID = 0;
(*pObj)[0]->data.lbe.bLBE = 0;
(*pObj)[stackIndex]->data.lbe.uniqueID = 0;
(*pObj)[stackIndex]->data.lbe.bLBE = 0;
return true;
}
}
return false;
}
void DestroyLBE(OBJECTTYPE* pObj)
void DestroyLBE(OBJECTTYPE* pObj, int stackIndex)
{
if(pObj->IsActiveLBE(0) == true)
if(pObj->IsActiveLBE(stackIndex) == true)
{
LBENODE* pLBE = pObj->GetLBEPointer(0);
LBENODE* pLBE = pObj->GetLBEPointer(stackIndex);
if(pLBE)
{
UINT16 plbesize = pLBE->inv.size();
@@ -206,8 +206,8 @@ void DestroyLBE(OBJECTTYPE* pObj)
}
}
(*pObj)[0]->data.lbe.uniqueID = 0;
(*pObj)[0]->data.lbe.bLBE = 0;
(*pObj)[stackIndex]->data.lbe.uniqueID = 0;
(*pObj)[stackIndex]->data.lbe.bLBE = 0;
return;
}
}
@@ -1009,7 +1009,11 @@ OBJECTTYPE* StackedObjectData::GetAttachmentAtIndex(UINT8 index)
}
if (iter != attachments.end()) {
return &(*iter);
OBJECTTYPE * attachment = &(*iter);
if (attachment->usItem > 0 && (attachment->ubNumberOfObjects != 1 || attachment->usItem > MAXITEMS || attachment->ubMission != 0) ) {
__debugbreak();
}
return attachment;
}
return 0;
}
+2 -2
View File
@@ -257,8 +257,8 @@ public:
bool checkLBEArrayIntegrity(bool verbose=false); // BOB: checks all worldItems for missing LBE info
void CreateLBE(OBJECTTYPE* pObj, UINT8 ubID, int numSubPockets);
bool DestroyLBEIfEmpty(OBJECTTYPE* pObj);
void DestroyLBE(OBJECTTYPE* pObj);
bool DestroyLBEIfEmpty(OBJECTTYPE* pObj, int stackIndex = 0);
void DestroyLBE(OBJECTTYPE* pObj, int stackIndex = 0);
void GetLBESlots(UINT32 LBEType, std::vector<INT8>& LBESlots);
void MoveItemsInSlotsToLBE( SOLDIERTYPE *pSoldier, std::vector<INT8>& LBESlots, LBENODE* pLBE, OBJECTTYPE* pObj);
+60 -11
View File
@@ -8248,7 +8248,8 @@ BOOLEAN ArmBomb( OBJECTTYPE * pObj, INT8 bSetting )
return( TRUE );
}
BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE* pAttachment, OBJECTTYPE * pNewObj, UINT8 subObject, SOLDIERTYPE * pSoldier, BOOLEAN fForceInseperable, BOOLEAN fRemoveProhibited )
// pAttachment will be filled with garbage data, pass a new OBJECTTYPE as pNewObj to get the removed attachment or pass NULL to indicate the attachment is to be deleted
BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE * pAttachment, OBJECTTYPE * pNewObj, UINT8 subObject, SOLDIERTYPE * pSoldier, BOOLEAN fForceInseperable, BOOLEAN fRemoveProhibited )
{
BOOLEAN objDeleted = FALSE;
std::vector<UINT16> usAttachmentSlotIndexVector;
@@ -8280,20 +8281,31 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE* pAttachment, OBJECTTYPE * pNew
//This is so that you can click to remove an attachment and it will take off THAT attachment and not the first one that just "looks" like it.
for (std::list<OBJECTTYPE>::iterator iter = (*this)[subObject]->attachments.begin();
iter != (*this)[subObject]->attachments.end(); ++iter){
//Compare the adress
if(&(*iter) == pAttachment)
{
removedAttachment = *pAttachment;
iter = (*this)[subObject]->RemoveAttachmentAtIter(iter);
pAttachment = NULL;
objDeleted = TRUE;
break;
}
// Bob: sanity check!
if (pAttachment != NULL && pAttachment->usItem > 0 && (pAttachment->ubNumberOfObjects != 1 || pAttachment->usItem > MAXITEMS || pAttachment->ubMission != 0)) {
__debugbreak();
}
//Compare the adress
if(&(*iter) == pAttachment)
{
removedAttachment = *pAttachment;
iter = (*this)[subObject]->RemoveAttachmentAtIter(iter);
pAttachment = NULL;
objDeleted = TRUE;
break;
}
}
//It is possible that the previous loop did not find the EXACT attachment we wanted to delete, look if there is one that is at least equal in data.
if(!objDeleted){
for (std::list<OBJECTTYPE>::iterator iter = (*this)[subObject]->attachments.begin();
iter != (*this)[subObject]->attachments.end(); ++iter){
// Bob: sanity check!
if (pAttachment != NULL && pAttachment->usItem > 0 && (pAttachment->ubNumberOfObjects != 1 || pAttachment->usItem > MAXITEMS || pAttachment->ubMission != 0)) {
__debugbreak();
}
//This compares the internal data of the objects.
if(*iter == *pAttachment)
{
@@ -8305,9 +8317,20 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE* pAttachment, OBJECTTYPE * pNew
}
}
}
// Bob: sanity check!
if (pAttachment != NULL && pAttachment->usItem > 0 && (pAttachment->ubNumberOfObjects != 1 || pAttachment->usItem > MAXITEMS || pAttachment->ubMission != 0)) {
__debugbreak();
}
if(!objDeleted)
return( FALSE );
// Bob: this function tends to leave this pointer in a messed up state, leading to other code to deal with bogus item data
if (pAttachment != NULL) {
__debugbreak();
}
//After removing an attachment, the ammo capacity might have changed.
if ( Item[this->usItem].usItemClass == IC_GUN && (*this)[subObject]->data.gun.usGunAmmoItem != NONE && (*this)[subObject]->data.gun.ubGunShotsLeft > 0 && oldMagSize != GetMagSize(this, subObject) )
{
@@ -8399,8 +8422,23 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE* pAttachment, OBJECTTYPE * pNew
RemoveProhibitedAttachments(pSoldier, &removedAttachment, removedAttachment.usItem);
RemoveProhibitedAttachments(pSoldier, this, this->usItem);
}
if(pNewObj != NULL)
// Bob: this function tends to leave this pointer in a messed up state, leading to other code to deal with bogus item data
if (pAttachment != NULL) {
__debugbreak();
}
if (pNewObj != NULL) {
*pNewObj = removedAttachment;
}
else {
*pAttachment = removedAttachment;
}
// Bob: this function tends to leave this pointer in a messed up state, leading to other code to deal with bogus item data
if (pAttachment != NULL) {
__debugbreak();
}
// Why is this here? By now, the object, pAttachment had been pointing to, has already been deconstructed via RemoveAttachmentAtIter.
@@ -8425,11 +8463,22 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE* pAttachment, OBJECTTYPE * pNew
pNewObj->AttachObject(NULL, &tmp, FALSE, 0, -1, 0);
}
}
// Bob: this function tends to leave this pointer in a messed up state, leading other code to deal with bogus item data
if (pAttachment != NULL) {
__debugbreak();
}
//Removing an attachment can alter slots, check them.
if(UsingNewAttachmentSystem()==true && fRemoveProhibited){
RemoveProhibitedAttachments(pSoldier, this, this->usItem);
}
// Bob: this function tends to leave this pointer in a messed up state, leading to other code to deal with bogus item data
if (pAttachment != NULL) {
__debugbreak();
}
//ADB ubWeight has been removed, see comments in OBJECTTYPE
//this->ubWeight = CalculateObjectWeight( this );
return( TRUE );
+16 -1
View File
@@ -2201,7 +2201,15 @@ BOOLEAN CalculateSoldierZPos( SOLDIERTYPE * pSoldier, UINT8 ubPosType, FLOAT * p
*pdZPos = ( WALL_HEIGHT_UNITS * 2 ) - 1;
}
*pdZPos += CONVERT_PIXELS_TO_HEIGHTUNITS( gpWorldLevelData[pSoldier->sGridNo].sHeight );
// Bob: check if sGridNo is set, otherwise bail out to avoid access violation
INT32 grid = pSoldier->sGridNo;
if (grid > 0) {
*pdZPos += CONVERT_PIXELS_TO_HEIGHTUNITS(gpWorldLevelData[grid].sHeight);
}
else {
// ScreenMsg(FONT_MCOLOR_LTRED, MSG_INTERFACE, L"CalculateSoldierZPos: Caught bad LOS height check!");
}
return( TRUE );
}
@@ -2505,6 +2513,13 @@ INT32 LocationToLocationLineOfSightTest( INT32 sStartGridNo, INT8 bStartLevel, I
{
FLOAT dStartZPos, dEndZPos;
INT16 sStartXPos, sStartYPos, sEndXPos, sEndYPos;
// Bob: prevent access violation
if (sStartGridNo < 0) {
// ScreenMsg(FONT_MCOLOR_LTRED, MSG_INTERFACE, L"LocationToLocationLineOfSightTest: Caught bad LOS check!");
return 0;
}
// UINT8 ubStartID;
// sevenfm: always use standing heights
+15
View File
@@ -6703,6 +6703,21 @@ void SeperateItems()
break;
}
}
// Bob: also empty out LBE items in sector inventory
if (gWorldItems[uiLoop].object.IsActiveLBE(x)) {
LBENODE * lbePtr = gWorldItems[uiLoop].object.GetLBEPointer(x);
for (auto lbeInvIter = lbePtr->inv.begin(); lbeInvIter != lbePtr->inv.end(); lbeInvIter++) {
OBJECTTYPE * LBEStack = lbeInvIter._Ptr;
if (LBEStack->usItem != 0 && LBEStack->exists()) {
AddItemToPool(gWorldItems[uiLoop].sGridNo, LBEStack, 1, gWorldItems[uiLoop].ubLevel, WORLD_ITEM_REACHABLE, -1);
}
}
DestroyLBE(&(gWorldItems[uiLoop].object), x);
}
}
}
}
+2 -2
View File
@@ -2449,7 +2449,7 @@ BOOLEAN LoadVehicleInformationFromSavedGameFile( HWFILE hFile, UINT32 uiSavedGam
{
// ! The id of the soldier was saved in the passenger pointer. The passenger pointer is converted back
// ! to a UINT8 so we can get the REAL pointer to the soldier.
pVehicleList[cnt].pPassengers[ubPassengerCnt] = FindSoldierByProfileID( (UINT8)pVehicleList[cnt].pPassengers[ ubPassengerCnt ], FALSE );
pVehicleList[cnt].pPassengers[ubPassengerCnt] = FindSoldierByProfileID( (UINT8)(pVehicleList[cnt].pPassengers[ ubPassengerCnt ]), FALSE );
}
}
else
@@ -2458,7 +2458,7 @@ BOOLEAN LoadVehicleInformationFromSavedGameFile( HWFILE hFile, UINT32 uiSavedGam
{
// ! The id of the soldier was saved in the passenger pointer. The passenger pointer is converted back
// ! to a UINT8 so we can get the REAL pointer to the soldier.
pVehicleList[cnt].pPassengers[ubPassengerCnt] = FindSoldierByProfileID( (UINT8)pVehicleList[cnt].pPassengers[ ubPassengerCnt ], FALSE );
pVehicleList[cnt].pPassengers[ubPassengerCnt] = FindSoldierByProfileID( (UINT8)(pVehicleList[cnt].pPassengers[ ubPassengerCnt ]), FALSE );
}
else
{
+1 -1
View File
@@ -210,7 +210,7 @@ BOOLEAN WriteClothesStats()
UINT32 cnt;
FilePrintf(hFile,"<CLOTHESLIST>\r\n");
for(cnt = 0; cnt < MAXITEMS; ++cnt)
for(cnt = 0; cnt < CLOTHES_MAX; ++cnt)
{
FilePrintf(hFile,"\t<CLOTHES>\r\n");
+7 -5
View File
@@ -188,14 +188,16 @@ MercStartingGearEndElementHandle(void *userData, const XML_Char *name)
else if(strcmp(name, "mName") == 0)
{
pData->curElement = ELEMENT;
if(MAX_CHAR_DATA_LENGTH >= strlen(pData->szCharData))
strcpy(pData->curMercStartingGear.mName,pData->szCharData);
if (strlen(pData->szCharData) < MAX_CHAR_DATA_LENGTH ) {
strncpy(pData->curMercStartingGear.mName, pData->szCharData, mNameLength);
}
else
{
strncpy(pData->curMercStartingGear.mName,pData->szCharData,MAX_CHAR_DATA_LENGTH);
pData->curMercStartingGear.mName[MAX_CHAR_DATA_LENGTH] = '\0';
strncpy(pData->curMercStartingGear.mName,pData->szCharData, mNameLength);
pData->curMercStartingGear.mName[mNameLength-1] = '\0';
}
for(int i=0;i<min((int)strlen(pData->szCharData),MAX_CHAR_DATA_LENGTH);i++)
for(int i=0;i<min( (int)strlen(pData->szCharData), mNameLength);i++)
{
temp = pData->szCharData[i];
pData->curMercStartingGear.mName[i] = temp;
+2 -2
View File
@@ -230,10 +230,10 @@ newCarEndElementHandle(void *userData, const XML_Char *name)
else
{
strncpy(pData->curNewCar.szIconFace,pData->szCharData,MAX_MAIN_VEHICLE_CHARS);
pData->curNewCar.szIconFace[MAX_MAIN_VEHICLE_CHARS] = '\0';
pData->curNewCar.szIconFace[MAX_MAIN_VEHICLE_CHARS-1] = '\0';
}
for(int i=0;i<min((int)strlen(pData->szCharData),MAX_MAIN_VEHICLE_CHARS);i++)
for(int i=0;i<min((int)strlen(pData->szCharData),MAX_MAIN_VEHICLE_CHARS-1);i++)
{
temp = pData->szCharData[i];
pData->curNewCar.szIconFace[i] = temp;
+6
View File
@@ -1218,6 +1218,12 @@ INT16 DistanceVisible( SOLDIERTYPE *pSoldier, INT8 bFacingDir, INT8 bSubjectDir,
return( 0 );
}
// Bob: if gridNo isn't set, this would cause a access violation later on
if (pSoldier->sGridNo < 0) {
// ScreenMsg(FONT_MCOLOR_LTRED, MSG_INTERFACE, L"DistanceVisible(): Caught bad LOS distance check!");
return(0);
}
// anv: some places in vehicle don't give passenger any view outside
INT8 bSeatIndex = GetSeatIndexFromSoldier( pSoldier );
if( bSeatIndex != (-1) )
+5 -2
View File
@@ -453,6 +453,9 @@ public:
}; // RECORDS
//////////////////////////////////////////////////////////////////////////////
#define mNameLength 80
#define mGearKitNameLength 80
// CHRISL: Class to handle profile equipment from XML_MercStartingGear
class MERCPROFILEGEAR {
public:
@@ -472,8 +475,8 @@ public:
UINT16 mIndex;
INT16 PriceModifier;
INT16 AbsolutePrice;
CHAR16 mGearKitName[80];
CHAR8 mName[80];
CHAR16 mGearKitName[mGearKitNameLength];
CHAR8 mName[mNameLength];
char endOfPOD; // marker for end of POD (plain old data)
std::vector<int> inv;
std::vector<int> iStatus;