diff --git a/GameSettings.cpp b/GameSettings.cpp index dcc4eb24..85af7cf3 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -2146,7 +2146,7 @@ void LoadSkillTraitsExternalSettings() // Flugente: COVERT OPS gSkillTraitValues.sCOMeleeCTHBonus = iniReader.ReadInteger("Covert Ops","COVERT_MELEE_CTH_BONUS", 40, 0, 200); gSkillTraitValues.sCoMeleeInstakillBonus = iniReader.ReadInteger("Covert Ops","COVERT_MELEE_INSTAKILL_BONUS", 35, 0, 200); - gSkillTraitValues.sCODisguiseAPReduction = iniReader.ReadInteger("Covert Ops","COVERT_DISGUISE_PERCENT_AP_REDUCTION", 20, 0, 100); + gSkillTraitValues.sCODisguiseAPReduction = iniReader.ReadInteger("Covert Ops","COVERT_DISGUISE_PERCENT_AP_REDUCTION", 20, 0, 50); gSkillTraitValues.sCOCloseDetectionRange = iniReader.ReadInteger("Covert Ops","COVERT_CLOSE_DETECTION_RANGE", 10, 0, 100); gSkillTraitValues.sCOCloseDetectionRangeSoldierCorpse = iniReader.ReadInteger("Covert Ops","COVERT_CLOSE_DETECTION_RANGE_SOLDIER_CORPSE", 5, 0, 100); } diff --git a/Init.cpp b/Init.cpp index 71c6d2fd..a6998e4c 100644 --- a/Init.cpp +++ b/Init.cpp @@ -384,6 +384,10 @@ BOOLEAN LoadExternalGameplayData(STR directoryName) strcat(fileName, FOODFILENAME); SGP_THROW_IFFALSE(ReadInFoodStats(fileName),FOODFILENAME); + strcpy(fileName, directoryName); + strcat(fileName, CLOTHESFILENAME); + SGP_THROW_IFFALSE(ReadInClothesStats(fileName),CLOTHESFILENAME); + strcpy(fileName, directoryName); strcat(fileName, ARMOURSFILENAME); SGP_THROW_IFFALSE(ReadInArmourStats(fileName),ARMOURSFILENAME); diff --git a/Tactical/Handle Items.cpp b/Tactical/Handle Items.cpp index d9eb658b..f2d9dd01 100644 --- a/Tactical/Handle Items.cpp +++ b/Tactical/Handle Items.cpp @@ -131,10 +131,12 @@ INT8 gbTrapDifficulty; BOOLEAN gfJustFoundBoobyTrap = FALSE; void StartBombMessageBox( SOLDIERTYPE * pSoldier, INT32 sGridNo ); -void StartTacticalFunctionSelectionMessageBox( SOLDIERTYPE * pSoldier, INT32 sGridNo, INT8 bLevel ); // added by Flugente -void CleanWeapons( BOOLEAN fCleanAll ); -void StartCorpseMessageBox( SOLDIERTYPE * pSoldier, INT32 sGridNo, INT8 bLevel ); // added by Flugente +// added by Flugente +void StartTacticalFunctionSelectionMessageBox( SOLDIERTYPE * pSoldier, INT32 sGridNo, INT8 bLevel ); +void CleanWeapons( BOOLEAN fCleanAll ); +void Strip( SOLDIERTYPE * pSoldier ); +void StartCorpseMessageBox( SOLDIERTYPE * pSoldier, INT32 sGridNo, INT8 bLevel ); BOOLEAN HandleCheckForBadChangeToGetThrough( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pTargetSoldier, INT32 sTargetGridNo , INT8 bLevel ) { @@ -4592,6 +4594,12 @@ void CleanWeapons( BOOLEAN fCleanAll ) } } +// take off custom clothes +void Strip( SOLDIERTYPE * pSoldier ) +{ + pSoldier->Strip(); +} + void BombMessageBoxCallBack( UINT8 ubExitValue ) { if (gpTempSoldier) @@ -4710,6 +4718,10 @@ void TacticalFunctionSelectionMessageBoxCallBack( UINT8 ubExitValue ) // clean all weapons CleanWeapons(TRUE); break; + case 4: + // take off custom clothes + Strip(gpTempSoldier); + break; default: break; } diff --git a/Tactical/Interface Panels.cpp b/Tactical/Interface Panels.cpp index 1ec1b0ce..c6585ae0 100644 --- a/Tactical/Interface Panels.cpp +++ b/Tactical/Interface Panels.cpp @@ -3357,7 +3357,7 @@ void SMInvClickCamoCallback( MOUSE_REGION * pRegion, INT32 iReason ) // Say OK acknowledge.... gpSMCurrentMerc->DoMercBattleSound( BATTLE_SOUND_COOL1 ); } - else if ( ApplySpyKit( gpSMCurrentMerc, gpItemPointer ) ) + else if ( ApplyClothes( gpSMCurrentMerc, gpItemPointer ) ) { // Dirty fInterfacePanelDirty = DIRTYLEVEL2; diff --git a/Tactical/Item Types.h b/Tactical/Item Types.h index 6704a0e2..c52982f2 100644 --- a/Tactical/Item Types.h +++ b/Tactical/Item Types.h @@ -859,6 +859,8 @@ extern OBJECTTYPE gTempObject; #define ITEM_DIRECTION_ANY 0x0000FF00 // ---------------------------------------------------------------- + + // replaces candamage //#define ITEM_DAMAGEABLE 0x0001 //// replaces canrepair @@ -1131,6 +1133,9 @@ typedef struct // Flugente: a flag that is necessary for transforming action items to objects with new abilities (for now, tripwire networks and directional explosives) UINT32 usActionItemFlag; + // Flugente: clothes type that 'links' to an entry in Clothes.xml + UINT32 clothestype; + } INVTYPE; // CHRISL: Added new structures to handle LBE gear and the two new XML files that will be needed to deal diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index 6276f0f8..2c857f20 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -9191,20 +9191,128 @@ BOOLEAN ApplyCammo( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAP return( TRUE ); } - // Flugente: apply disguise -BOOLEAN ApplySpyKit( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj) -{ - if (pObj->exists() == false || !HasItemFlag(pObj->usItem, (CLOTHES_CIVILIAN)) ) +// Flugente: apply clothes, and eventually disguise +BOOLEAN ApplyClothes( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj) +{ + // this will only work with the new trait system + if (!gGameOptions.fNewTraitSystem) { - return( FALSE ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_ERROR_OLDTRAITS] ); + return FALSE; } - // we get the civilian disguise. AP costs will be checked and deducted here - if ( !pSoldier->DisguiseAsCivilian() ) - return FALSE; + if ( !pSoldier || pObj->exists() == false ) + return( FALSE ); - UseKitPoints( pObj, 100, pSoldier ); + UINT8 skilllevel = NUM_SKILL_TRAITS( pSoldier, COVERT_NT ); + + INT16 apcost = (APBPConstants[AP_DISGUISE] * ( 100 - gSkillTraitValues.sCODisguiseAPReduction * skilllevel))/100; + if ( !EnoughPoints( pSoldier, apcost, 0, TRUE ) ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NOT_ENOUGH_APS] ); + return( FALSE ); + } + + // determine clothes type + UINT32 clothestype = Item[pObj->usItem].clothestype; + + // if not a clothes item, nothing to see here + if ( clothestype == 0 || clothestype > CLOTHES_MAX ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_UNIFORM_FOUND] ); + return( FALSE); + } + UINT8 filler = 0; + // if it has a vest, wear it + bool newvest = FALSE; + if ( GetPaletteRepIndexFromID(Clothes[clothestype].vest, &filler) ) + newvest = TRUE; + + // if it has pants, wear them + bool newpants = FALSE; + if ( GetPaletteRepIndexFromID(Clothes[clothestype].pants, &filler) ) + newpants = TRUE; + + if ( newvest || newpants ) + { + UINT16 usPaletteAnimSurface = LoadSoldierAnimationSurface( pSoldier, pSoldier->usAnimState ); + + if ( usPaletteAnimSurface != INVALID_ANIMATION_SURFACE ) + { + if ( newvest ) + { + // if we are already wearing a vest, give us back that item + if ( pSoldier->bSoldierFlagMask & SOLDIER_NEW_VEST ) + { + UINT16 vestitem = 0; + if ( GetFirstClothesItemWithSpecificData(&vestitem, pSoldier->VestPal, "blank") ) + { + CreateItem( vestitem, 100, &gTempObject ); + if ( !AutoPlaceObject( pSoldier, &gTempObject, FALSE ) ) + AddItemToPool( pSoldier->sGridNo, &gTempObject, 1, 0, 0, -1 ); + } + else + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CLOTHES_ITEM] ); + } + + SET_PALETTEREP_ID( pSoldier->VestPal, Clothes[clothestype].vest ); + pSoldier->bSoldierFlagMask |= SOLDIER_NEW_VEST; + } + + if ( newpants ) + { + // if we are already wearing a vest, give us back that item + if ( pSoldier->bSoldierFlagMask & SOLDIER_NEW_PANTS ) + { + UINT16 pantsitem = 0; + if ( GetFirstClothesItemWithSpecificData(&pantsitem, "blank", pSoldier->PantsPal) ) + { + CreateItem( pantsitem, 100, &gTempObject ); + if ( !AutoPlaceObject( pSoldier, &gTempObject, FALSE ) ) + AddItemToPool( pSoldier->sGridNo, &gTempObject, 1, 0, 0, -1 ); + } + else + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CLOTHES_ITEM] ); + } + + SET_PALETTEREP_ID( pSoldier->PantsPal, Clothes[clothestype].pants ); + pSoldier->bSoldierFlagMask |= SOLDIER_NEW_PANTS; + } + + // Use palette from HVOBJECT, then use substitution for pants, etc + memcpy( pSoldier->p8BPPPalette, gAnimSurfaceDatabase[ usPaletteAnimSurface ].hVideoObject->pPaletteEntry, sizeof( pSoldier->p8BPPPalette ) * 256 ); + + SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->HeadPal ); + SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->VestPal ); + SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->PantsPal ); + SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->SkinPal ); + + pSoldier->CreateSoldierPalettes(); + + UseKitPoints( pObj, 100, pSoldier ); + + DeductPoints( pSoldier, apcost, 0 ); + } + + if ( pSoldier->bSoldierFlagMask & SOLDIER_NEW_VEST && pSoldier->bSoldierFlagMask & SOLDIER_NEW_PANTS ) + { + // first, remove the covert flags, adn then reapply the correct ones, in case we switch between civilina and military garb + pSoldier->bSoldierFlagMask &= ~(SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER); + + // we now have to determine wether we are currently wearing civilian or military clothes + for ( int i = UNIFORM_ENEMY_ADMIN; i <= UNIFORM_ENEMY_ELITE; ++i ) + { + if ( pSoldier->VestPal == gUniformColors[ i ].vest && pSoldier->PantsPal == gUniformColors[ i ].pants ) + pSoldier->bSoldierFlagMask |= SOLDIER_COVERT_SOLDIER; + } + + // if not dressed as a soldier, we must be dressed as a civilian + if ( !(pSoldier->bSoldierFlagMask & SOLDIER_COVERT_SOLDIER) ) + pSoldier->bSoldierFlagMask |= SOLDIER_COVERT_CIV; + } + } + return( TRUE ); } @@ -14529,4 +14637,57 @@ FLOAT GetItemDirtIncreaseFactor( OBJECTTYPE * pObj, BOOLEAN fConsiderAmmo ) dirtincreasefactor = max(0.0f, dirtincreasefactor); return dirtincreasefactor; -} \ No newline at end of file +} + +// Flugente: retrieve a specific clothes item, if such a thing exists +BOOLEAN GetFirstClothesItemWithSpecificData( UINT16* pusItem, PaletteRepID aPalVest, PaletteRepID aPalPants ) +{ + bool vestok = FALSE; + bool pantsok = FALSE; + + UINT8 filler = 0; + if ( !GetPaletteRepIndexFromID(aPalVest, &filler) ) + vestok = TRUE; + + if ( !GetPaletteRepIndexFromID(aPalPants, &filler) ) + pantsok = TRUE; + + register UINT16 i; + for (i = 1; i < MAXITEMS; ++i) + { + if ( Item[i].clothestype > 0 ) + { + bool tmpvestok = vestok; + bool tmppantsok = pantsok; + + UINT8 vestpalid = 0; + GetPaletteRepIndexFromID(aPalVest, &vestpalid); + + // if we are looking for vests, do so + if ( !tmpvestok ) + { + if ( COMPARE_PALETTEREP_ID(aPalVest, Clothes[Item[i].clothestype].vest) ) + { + tmpvestok = TRUE; + } + } + + // if we are looking for pants, do so + if ( !tmppantsok ) + { + if ( COMPARE_PALETTEREP_ID(aPalPants, Clothes[Item[i].clothestype].pants) ) + { + tmppantsok = TRUE; + } + } + + if ( tmpvestok && tmppantsok ) + { + *pusItem = i; + return( TRUE ); + } + } + } + + return( FALSE ); +} diff --git a/Tactical/Items.h b/Tactical/Items.h index d9d3e435..4d1bdfe5 100644 --- a/Tactical/Items.h +++ b/Tactical/Items.h @@ -196,7 +196,7 @@ void WaterDamage( SOLDIERTYPE *pSoldier ); INT8 FindObj( SOLDIERTYPE * pSoldier, UINT16 usItem, INT8 bLower = 0, INT8 bUpper = NUM_INV_SLOTS ); BOOLEAN ApplyCammo( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAPs ); -BOOLEAN ApplySpyKit( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj); // Flugente: apply disguise +BOOLEAN ApplyClothes( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj); // Flugente: apply clothes, and eventually disguise UINT32 ConvertProfileMoneyValueToObjectTypeMoneyValue( UINT8 ubStatus ); UINT8 ConvertObjectTypeMoneyValueToProfileMoneyValue( UINT32 uiMoneyAmount ); @@ -498,6 +498,9 @@ UINT8 GetFirstPocketOnItem(UINT16 usIndex); INT8 GetNumberAltFireAimLevels( SOLDIERTYPE * pSoldier, INT32 iGridNo ); +// Flugente: retrieve a specific clothes item, if such a thing exists +BOOLEAN GetFirstClothesItemWithSpecificData( UINT16* pusItem, PaletteRepID aPalVest, PaletteRepID aPalPants ); + #endif diff --git a/Tactical/Rotting Corpses.cpp b/Tactical/Rotting Corpses.cpp index 22cd697d..7154a9bb 100644 --- a/Tactical/Rotting Corpses.cpp +++ b/Tactical/Rotting Corpses.cpp @@ -897,15 +897,7 @@ BOOLEAN TurnSoldierIntoCorpse( SOLDIERTYPE *pSoldier, BOOLEAN fRemoveMerc, BOOLE memcpy( &(Corpse.name), &(pSoldier->name), sizeof(CHAR16) * 10 ); Corpse.name[9] = '\0'; #endif - - // Flugente: mark if this was an army soldier ( we use this to steal his clothes later on ) - if ( pSoldier->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR ) - Corpse.usFlags |= ROTTING_CORPSE_FROM_ADMIN; - else if ( pSoldier->ubSoldierClass == SOLDIER_CLASS_ARMY ) - Corpse.usFlags |= ROTTING_CORPSE_FROM_TROOP; - else if ( pSoldier->ubSoldierClass == SOLDIER_CLASS_ELITE ) - Corpse.usFlags |= ROTTING_CORPSE_FROM_ELITE; - + // if this soldier's uniform was damaged (gunfire, blade attacks, explosions) then don't allow to take the uniform. We can't stay hidden if we're covered in blood :-) if ( pSoldier->bSoldierFlagMask &SOLDIER_DAMAGED_UNIFORM ) Corpse.usFlags |= ROTTING_CORPSE_CLOTHES_TAKEN; @@ -1962,15 +1954,11 @@ BOOLEAN IsValidStripCorpse( ROTTING_CORPSE *pCorpse ) if ( pCorpse->def.ubType == ROTTING_STAGE2 || (pCorpse->def.usFlags & ROTTING_CORPSE_CLOTHES_TAKEN) ) return( FALSE ); - // is there a uniform we can take? - if ( !(pCorpse->def.usFlags & (ROTTING_CORPSE_FROM_ADMIN|ROTTING_CORPSE_FROM_TROOP|ROTTING_CORPSE_FROM_ELITE)) ) - return( FALSE ); - - return( CorpseOkToDress(pCorpse, NULL) ); + return( CorpseOkToDress(pCorpse) ); } -// Flugente: take the clothes off a corpse and wear them +// Flugente: take the clothes off a corpse void StripCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel ) { ROTTING_CORPSE *pCorpse = GetCorpseAtGridNo( sGridNo, bLevel ); @@ -1981,20 +1969,35 @@ void StripCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel ) // can this thing be stripped? if ( IsValidStripCorpse( pCorpse ) ) { - // if this fits our body, try to wear it - if ( CorpseOkToDress(pCorpse, pSoldier) && pSoldier->DisguiseAsSoldierFromCorpse( pCorpse->def.usFlags ) ) + // determine which clothes to spawn + UINT16 vestitem = 0; + if ( GetFirstClothesItemWithSpecificData(&vestitem, pCorpse->def.VestPal, "blank") ) { - // we took the clothes, mark this - pCorpse->def.usFlags |= ROTTING_CORPSE_CLOTHES_TAKEN; + CreateItem( vestitem, 100, &gTempObject ); + if ( !AutoPlaceObject( pSoldier, &gTempObject, FALSE ) ) + AddItemToPool( pSoldier->sGridNo, &gTempObject, 1, 0, 0, -1 ); } else - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCorpseTextStr[STR_CORPSE_NO_STRIPPING_POSSIBLE], pSoldier->name ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CLOTHES_ITEM] ); + + UINT16 pantsitem = 0; + if ( GetFirstClothesItemWithSpecificData(&pantsitem, "blank", pCorpse->def.PantsPal) ) + { + CreateItem( pantsitem, 100, &gTempObject ); + if ( !AutoPlaceObject( pSoldier, &gTempObject, FALSE ) ) + AddItemToPool( pSoldier->sGridNo, &gTempObject, 1, 0, 0, -1 ); + } + else + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CLOTHES_ITEM] ); + + // we took the clothes, mark this + pCorpse->def.usFlags |= ROTTING_CORPSE_CLOTHES_TAKEN; } else ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCorpseTextStr[STR_CORPSE_NO_CLOTHESFOUND] ); } -// Flugente: can clothes be taken off of this corpse? +// Flugente: can this corpse be carried? BOOLEAN IsValidTakeCorpse( ROTTING_CORPSE *pCorpse ) { if ( pCorpse->def.ubType >= BLOODCAT_DEAD || pCorpse->def.ubType == NO_CORPSE ) @@ -2271,10 +2274,7 @@ BOOLEAN AddCorpseFromObject(OBJECTTYPE* pObj, INT32 sGridNo, INT8 bLevel ) SET_PALETTEREP_ID( Corpse.PantsPal, "BLUEPANTS" ); else SET_PALETTEREP_ID( Corpse.PantsPal, "BEIGEPANTS" ); - - //SET_PALETTEREP_ID( Corpse.VestPal, gUniformColors[ UNIFORM_ENEMY_TROOP ].vest ); - //SET_PALETTEREP_ID( Corpse.PantsPal, gUniformColors[ UNIFORM_ENEMY_TROOP ].pants ); - + Corpse.ubDirection = NORTH; Corpse.uiTimeOfDeath = GetWorldTotalMin(); @@ -2299,15 +2299,7 @@ BOOLEAN AddCorpseFromObject(OBJECTTYPE* pObj, INT32 sGridNo, INT8 bLevel ) if ( (*pObj)[0]->data.sObjectFlag & CORPSE_STRIPPED ) gRottingCorpse[ iCorpseID ].def.usFlags |= ROTTING_CORPSE_CLOTHES_TAKEN; - - // TODO: change this so it always fits, not dependant these colours - if ( (*pObj)[0]->data.sObjectFlag & CORPSE_VEST_YELLOW && (*pObj)[0]->data.sObjectFlag & CORPSE_PANTS_GREEN ) - gRottingCorpse[ iCorpseID ].def.usFlags |= ROTTING_CORPSE_FROM_ADMIN; - else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_VEST_RED && (*pObj)[0]->data.sObjectFlag & CORPSE_PANTS_GREEN ) - gRottingCorpse[ iCorpseID ].def.usFlags |= ROTTING_CORPSE_FROM_TROOP; - else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_VEST_BLACK && (*pObj)[0]->data.sObjectFlag & CORPSE_PANTS_BLACK ) - gRottingCorpse[ iCorpseID ].def.usFlags |= ROTTING_CORPSE_FROM_ELITE; - + #ifdef ENABLE_ZOMBIES if ( (*pObj)[0]->data.sObjectFlag & CORPSE_NO_ZOMBIE_RISE ) gRottingCorpse[ iCorpseID ].def.usFlags |= ROTTING_CORPSE_NEVER_RISE_AGAIN; @@ -2984,7 +2976,7 @@ UINT8 GetNearestRottingCorpseAIWarning( INT32 sGridNo ) // Flugente: can we take the clothes of this corpse? // calling this with NULL for soldier will give a general answer for any bodytype -BOOLEAN CorpseOkToDress( ROTTING_CORPSE * pCorpse, SOLDIERTYPE* pSoldier ) +BOOLEAN CorpseOkToDress( ROTTING_CORPSE* pCorpse ) { if ( !pCorpse ) return FALSE; @@ -3007,16 +2999,6 @@ BOOLEAN CorpseOkToDress( ROTTING_CORPSE * pCorpse, SOLDIERTYPE* pSoldier ) case S_DEAD2: case C_DEAD1: case C_DEAD2: - if ( pSoldier ) - { - if ( pSoldier->ubBodyType == REGMALE ) - return TRUE; - } - else - return TRUE; - - break; - case MMERC_JFK: case MMERC_BCK: case MMERC_FWD: @@ -3026,17 +3008,7 @@ BOOLEAN CorpseOkToDress( ROTTING_CORPSE * pCorpse, SOLDIERTYPE* pSoldier ) case MMERC_FALL: case MMERC_FALLF: case FT_DEAD1: - case FT_DEAD2: - if ( pSoldier ) - { - if ( pSoldier->ubBodyType == BIGMALE || pSoldier->ubBodyType == STOCKYMALE ) - return TRUE; - } - else - return TRUE; - - break; - + case FT_DEAD2: case FMERC_JFK: case FMERC_BCK: case FMERC_FWD: @@ -3047,14 +3019,7 @@ BOOLEAN CorpseOkToDress( ROTTING_CORPSE * pCorpse, SOLDIERTYPE* pSoldier ) case FMERC_FALLF: case W_DEAD1: case W_DEAD2: - if ( pSoldier ) - { - if ( pSoldier->ubBodyType == REGFEMALE ) - return TRUE; - } - else - return TRUE; - + return TRUE; break; default: diff --git a/Tactical/Rotting Corpses.h b/Tactical/Rotting Corpses.h index 19c9bf91..edc66917 100644 --- a/Tactical/Rotting Corpses.h +++ b/Tactical/Rotting Corpses.h @@ -94,9 +94,6 @@ enum RottingCorpseDefines #define ROTTING_CORPSE_GUTTED 0x00002000 // corpse has been gutted #define ROTTING_CORPSE_CLOTHES_TAKEN 0x00004000 // corpse is without clothes (atm not visually) -#define ROTTING_CORPSE_FROM_ADMIN 0x00010000 // corpse is from a admin (used to take his clothes) -#define ROTTING_CORPSE_FROM_TROOP 0x00020000 // corpse is from a regular soldier (used to take his clothes) -#define ROTTING_CORPSE_FROM_ELITE 0x00040000 // corpse is from a elite soldier (used to take his clothes) typedef struct { UINT8 ubType; @@ -236,6 +233,6 @@ UINT8 GetNearestRottingCorpseAIWarning( INT32 sGridNo ); #endif // Flugente: can we take the clothes of this corpse? -BOOLEAN CorpseOkToDress( ROTTING_CORPSE * pCorpse, SOLDIERTYPE* pSoldier ); +BOOLEAN CorpseOkToDress( ROTTING_CORPSE* pCorpse ); #endif \ No newline at end of file diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index ef058122..a7394d81 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -15068,7 +15068,38 @@ BOOLEAN SOLDIERTYPE::RecognizeAsCombatant(UINT8 ubTargetID) // dress up in our natural state void SOLDIERTYPE::LooseDisguise( void ) +{ + // loose any covert flags + this->bSoldierFlagMask &= ~(SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER); +} + +// take off any clothes item and switch back to original clothes +// no - this function does not want you think it does. Leave Fox alone, you perv. +void SOLDIERTYPE::Strip() { + // loose any covert and clothes flags + this->bSoldierFlagMask &= ~(SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER|SOLDIER_NEW_VEST|SOLDIER_NEW_PANTS); + + UINT16 vestitem = 0; + if ( GetFirstClothesItemWithSpecificData(&vestitem, this->VestPal, "blank") ) + { + CreateItem( vestitem, 100, &gTempObject ); + if ( !AutoPlaceObject( this, &gTempObject, FALSE ) ) + AddItemToPool( this->sGridNo, &gTempObject, 1, 0, 0, -1 ); + } + else + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CLOTHES_ITEM] ); + + UINT16 pantsitem = 0; + if ( GetFirstClothesItemWithSpecificData(&pantsitem, "blank", this->PantsPal) ) + { + CreateItem( pantsitem, 100, &gTempObject ); + if ( !AutoPlaceObject( this, &gTempObject, FALSE ) ) + AddItemToPool( this->sGridNo, &gTempObject, 1, 0, 0, -1 ); + } + else + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CLOTHES_ITEM] ); + // show our true colours UINT16 usPaletteAnimSurface = LoadSoldierAnimationSurface( this, this->usAnimState ); @@ -15093,183 +15124,8 @@ void SOLDIERTYPE::LooseDisguise( void ) this->CreateSoldierPalettes(); } - - // loose any covert flags - // if we are disguised as a civilian, remove that flag, and give us back a civilian clothes item - if ( this->bSoldierFlagMask & SOLDIER_COVERT_CIV ) - { - this->bSoldierFlagMask &= ~SOLDIER_COVERT_CIV; - - UINT16 civilianclothesitem = 0; - if ( GetFirstItemWithFlag(&civilianclothesitem, CLOTHES_CIVILIAN) ) - { - CreateItem( civilianclothesitem, 100, &gTempObject ); - - if ( !AutoPlaceObject( this, &gTempObject, FALSE ) ) - AddItemToPool( sGridNo, &gTempObject, 1, 0, 0, -1 ); - } - else - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CLOTHES_ITEM] ); - } - - // if we are also disguised as a soldier, remove that flag - if ( this->bSoldierFlagMask & SOLDIER_COVERT_SOLDIER ) - { - this->bSoldierFlagMask &= ~SOLDIER_COVERT_SOLDIER; - } } -// dress up like a civilian -BOOLEAN SOLDIERTYPE::DisguiseAsCivilian( void ) -{ - // this will only work with the new trait system - if (!gGameOptions.fNewTraitSystem) - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_ERROR_OLDTRAITS] ); - return FALSE; - } - - UINT8 skilllevel = NUM_SKILL_TRAITS( this, COVERT_NT ); - - INT16 apcost = (APBPConstants[AP_DISGUISE] * ( gSkillTraitValues.sCODisguiseAPReduction * skilllevel))/100; - if ( !EnoughPoints( this, apcost, 0, TRUE ) ) - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NOT_ENOUGH_APS] ); - return( FALSE ); - } - - this->bSoldierFlagMask |= SOLDIER_COVERT_CIV; - - // wear an enemy uniform - UINT16 usPaletteAnimSurface = LoadSoldierAnimationSurface( this, this->usAnimState ); - - if ( usPaletteAnimSurface != INVALID_ANIMATION_SURFACE ) - { - // wear something random - switch( Random( 7 ) ) - { - case 0: SET_PALETTEREP_ID( this->VestPal, "WHITEVEST" ); break; - case 1: SET_PALETTEREP_ID( this->VestPal, "BLACKSHIRT" ); break; - case 2: SET_PALETTEREP_ID( this->VestPal, "PURPLESHIRT" ); break; - case 3: SET_PALETTEREP_ID( this->VestPal, "BLUEVEST" ); break; - case 4: SET_PALETTEREP_ID( this->VestPal, "BROWNVEST" ); break; - case 5: SET_PALETTEREP_ID( this->VestPal, "JEANVEST" ); break; - case 6: SET_PALETTEREP_ID( this->VestPal, "REDVEST" ); break; - } - - switch( Random( 3 ) ) - { - case 0: SET_PALETTEREP_ID( this->PantsPal, "TANPANTS" ); break; - case 1: SET_PALETTEREP_ID( this->PantsPal, "BEIGEPANTS" ); break; - case 2: SET_PALETTEREP_ID( this->PantsPal, "GREENPANTS" ); break; - } - - // Use palette from HVOBJECT, then use substitution for pants, etc - memcpy( this->p8BPPPalette, gAnimSurfaceDatabase[ usPaletteAnimSurface ].hVideoObject->pPaletteEntry, sizeof( this->p8BPPPalette ) * 256 ); - - SetPaletteReplacement( this->p8BPPPalette, this->HeadPal ); - SetPaletteReplacement( this->p8BPPPalette, this->VestPal ); - SetPaletteReplacement( this->p8BPPPalette, this->PantsPal ); - SetPaletteReplacement( this->p8BPPPalette, this->SkinPal ); - - this->CreateSoldierPalettes(); - } - else - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_BAD_PALETTE] ); - - // if we are also disguised as a soldier, remove that flag - if ( this->bSoldierFlagMask & SOLDIER_COVERT_SOLDIER ) - { - this->bSoldierFlagMask &= ~SOLDIER_COVERT_SOLDIER; - } - - DeductPoints( this, apcost, 0 ); - - return TRUE; -} - -// dress up like an enemy soldier -BOOLEAN SOLDIERTYPE::DisguiseAsSoldierFromCorpse( UINT32 usFlag ) -{ - // this will only work with the new trait system - if (!gGameOptions.fNewTraitSystem) - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_ERROR_OLDTRAITS] ); - return FALSE; - } - - // action is only possible if we have the covert ops trait - UINT8 skilllevel = NUM_SKILL_TRAITS( this, COVERT_NT ); - if ( skilllevel < 1) - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_SKILL] ); - return FALSE; - } - - INT16 apcost = (APBPConstants[AP_DISGUISE] * ( gSkillTraitValues.sCODisguiseAPReduction * skilllevel))/100; - if ( !EnoughPoints( this, apcost, 0, TRUE ) ) - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NOT_ENOUGH_APS] ); - return( FALSE ); - } - - UINT8 uniformtype = 0; - - if ( usFlag & ROTTING_CORPSE_FROM_ADMIN ) - uniformtype = UNIFORM_ENEMY_ADMIN; - else if ( usFlag & ROTTING_CORPSE_FROM_TROOP ) - uniformtype = UNIFORM_ENEMY_TROOP; - else if ( usFlag & ROTTING_CORPSE_FROM_ELITE ) - uniformtype = UNIFORM_ENEMY_ELITE; - else - { - // no uniform here, so nothing to wear - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_UNIFORM_FOUND] ); - return FALSE; - } - - this->bSoldierFlagMask |= SOLDIER_COVERT_SOLDIER; - - // wear an enemy uniform - UINT16 usPaletteAnimSurface = LoadSoldierAnimationSurface( this, this->usAnimState ); - - if ( usPaletteAnimSurface != INVALID_ANIMATION_SURFACE ) - { - SET_PALETTEREP_ID(this->VestPal, gUniformColors[ uniformtype ].vest ); - SET_PALETTEREP_ID(this->PantsPal, gUniformColors[ uniformtype ].pants ); - - // Use palette from HVOBJECT, then use substitution for pants, etc - memcpy( this->p8BPPPalette, gAnimSurfaceDatabase[ usPaletteAnimSurface ].hVideoObject->pPaletteEntry, sizeof( this->p8BPPPalette ) * 256 ); - - SetPaletteReplacement( this->p8BPPPalette, this->HeadPal ); - SetPaletteReplacement( this->p8BPPPalette, this->VestPal ); - SetPaletteReplacement( this->p8BPPPalette, this->PantsPal ); - SetPaletteReplacement( this->p8BPPPalette, this->SkinPal ); - - this->CreateSoldierPalettes(); - } - - // if we are disguised as a civilian, remove that flag, and give us back a civilian clothes item - if ( this->bSoldierFlagMask & SOLDIER_COVERT_CIV ) - { - this->bSoldierFlagMask &= ~SOLDIER_COVERT_CIV; - - UINT16 civilianclothesitem = 0; - if ( GetFirstItemWithFlag(&civilianclothesitem, CLOTHES_CIVILIAN) ) - { - CreateItem( civilianclothesitem, 100, &gTempObject ); - AddItemToPool( sGridNo, &gTempObject, 1, 0, 0, -1 ); - } - else - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CLOTHES_ITEM] ); - } - - DeductPoints( this, apcost, 0 ); - - return TRUE; -} - - INT32 CheckBleeding( SOLDIERTYPE *pSoldier ) { INT8 bBandaged; //,savedOurTurn; diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index 2b61a674..4d007463 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -349,11 +349,11 @@ enum #define SOLDIER_COVERT_SOLDIER 0x00000008 //8 // Soldier is currently disguised as an enemy soldier #define SOLDIER_DAMAGED_UNIFORM 0x00000010 //16 // Soldier's uniform is damged (and thus can't be taken off of his corpse) -#define SOLDIER_COVERT_NPC_SPECIAL 0x00000020 //32 // Special flag for NPCs wehn recruited (used for covert stuff) -/*#define WH40K_JUMPPACK 0x00000040 //64 -#define WH40K_DISPLACER 0x00000080 //128 +#define SOLDIER_COVERT_NPC_SPECIAL 0x00000020 //32 // Special flag for NPCs when recruited (used for covert stuff) +#define SOLDIER_NEW_VEST 0x00000040 //64 // Soldier is wearing new vest. if having both vest and pants, he can disguise +#define SOLDIER_NEW_PANTS 0x00000080 //128 // Soldier is wearing new pants -#define WH40K_ROSARIUS 0x00000100 //256 +/*#define WH40K_ROSARIUS 0x00000100 //256 #define WH40K_SEAL 0x00000200 //512 #define WH40K_POWER_WEAPON 0x00000400 //1024 #define ENEMY_NET_4_LVL_3 0x00000800 //2048 @@ -394,6 +394,19 @@ typedef struct // HEADROCK HAM 3.6: Uniform colors for the different soldier classes extern UNIFORMCOLORS gUniformColors[NUM_UNIFORMS]; +// Flugente: a structure for clothing items +typedef struct +{ + UINT16 uiIndex; + CHAR16 szName[80]; // name of these clothes + PaletteRepID vest; + PaletteRepID pants; +} CLOTHES_STRUCT; + +#define CLOTHES_MAX 50 + +extern CLOTHES_STRUCT Clothes[CLOTHES_MAX]; + // This macro should be used whenever we want to see if someone is neutral // IF WE ARE CONSIDERING ATTACKING THEM. Creatures & bloodcats will attack neutrals // but they can't attack empty vehicles!! @@ -1476,13 +1489,10 @@ public: BOOLEAN RecognizeAsCombatant(UINT8 ubTargetID); // loose disguise, dress up in our natural state - void LooseDisguise( void ); + void LooseDisguise( void ); - // dress up like a civilian - BOOLEAN DisguiseAsCivilian( void ); - - // dress up like an enemy soldier - BOOLEAN DisguiseAsSoldierFromCorpse( UINT32 usFlag ); + // take off any clothes item and switch back to original clothes + void Strip(); ////////////////////////////////////////////////////////////////////////////// }; // SOLDIERTYPE; diff --git a/Tactical/XML.h b/Tactical/XML.h index d7c95c11..b21e5208 100644 --- a/Tactical/XML.h +++ b/Tactical/XML.h @@ -67,6 +67,7 @@ typedef PARSE_STAGE; #define EXPLOSIVESFILENAME "Explosives.xml" #define DRUGSFILENAME "Drugs.xml" #define FOODFILENAME "Food.xml" +#define CLOTHESFILENAME "Clothes.xml" #define AMMOFILENAME "AmmoStrings.xml" #define AMMOTYPESFILENAME "AmmoTypes.xml" #define INCOMPATIBLEATTACHMENTSFILENAME "IncompatibleAttachments.xml" @@ -306,6 +307,10 @@ extern BOOLEAN WriteDrugsStats(); extern BOOLEAN ReadInFoodStats(STR fileName); extern BOOLEAN WriteFoodStats(); +// Flugente: clothes +extern BOOLEAN ReadInClothesStats(STR fileName); +extern BOOLEAN WriteClothesStats(); + extern BOOLEAN ReadInAmmoStats(STR fileName); extern BOOLEAN WriteAmmoStats(); diff --git a/Tactical/XML_Clothes.cpp b/Tactical/XML_Clothes.cpp new file mode 100644 index 00000000..31c80927 --- /dev/null +++ b/Tactical/XML_Clothes.cpp @@ -0,0 +1,228 @@ +#ifdef PRECOMPILEDHEADERS + #include "Tactical All.h" +#else + #include "sgp.h" + #include "overhead.h" + #include "Debug Control.h" + #include "expat.h" + #include "XML.h" +#endif + +struct +{ + PARSE_STAGE curElement; + + CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1]; + CLOTHES_STRUCT curClothes; + CLOTHES_STRUCT* curArray; + UINT32 maxArraySize; + + UINT32 currentDepth; + UINT32 maxReadDepth; +} +typedef clothesParseData; + +// Array to hold clothes data +CLOTHES_STRUCT Clothes[CLOTHES_MAX]; + +static void XMLCALL +clothesStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts) +{ + clothesParseData * pData = (clothesParseData *)userData; + + if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element? + { + if(strcmp(name, "CLOTHESLIST") == 0 && pData->curElement == ELEMENT_NONE) + { + pData->curElement = ELEMENT_LIST; + + memset(pData->curArray,0,sizeof(CLOTHES_STRUCT)*pData->maxArraySize); + + pData->maxReadDepth++; //we are not skipping this element + } + else if(strcmp(name, "CLOTHES") == 0 && pData->curElement == ELEMENT_LIST) + { + pData->curElement = ELEMENT; + + memset(&pData->curClothes,0,sizeof(CLOTHES_STRUCT)); + + pData->maxReadDepth++; //we are not skipping this element + } + else if(pData->curElement == ELEMENT && + (strcmp(name, "uiIndex") == 0 || + strcmp(name, "szName") == 0 || + strcmp(name, "Vest") == 0 || + strcmp(name, "Pants") == 0 )) + { + pData->curElement = ELEMENT_PROPERTY; + + pData->maxReadDepth++; //we are not skipping this element + } + + pData->szCharData[0] = '\0'; + } + + pData->currentDepth++; + +} + +static void XMLCALL +clothesCharacterDataHandle(void *userData, const XML_Char *str, int len) +{ + clothesParseData * pData = (clothesParseData *)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 +clothesEndElementHandle(void *userData, const XML_Char *name) +{ + clothesParseData * pData = (clothesParseData *)userData; + + if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading + { + if(strcmp(name, "CLOTHESLIST") == 0) + { + pData->curElement = ELEMENT_NONE; + } + else if(strcmp(name, "CLOTHES") == 0) + { + pData->curElement = ELEMENT_LIST; + + // we do NOT want to read the first entry -> move stuff by 1 + if(pData->curClothes.uiIndex < pData->maxArraySize) + { + pData->curArray[pData->curClothes.uiIndex] = pData->curClothes; //write the clothes into the table + } + } + else if(strcmp(name, "uiIndex") == 0) + { + pData->curElement = ELEMENT; + pData->curClothes.uiIndex = (UINT16) atol(pData->szCharData); + } + else if(strcmp(name, "szName") == 0) + { + pData->curElement = ELEMENT; + // not needed, but it's there for informational purposes + } + else if(strcmp(name, "Vest") == 0 ) + { + pData->curElement = ELEMENT; + + strcpy(pData->curClothes.vest, pData->szCharData); + } + else if(strcmp(name, "Pants") == 0 ) + { + pData->curElement = ELEMENT; + + strcpy(pData->curClothes.pants, pData->szCharData); + } + + pData->maxReadDepth--; + } + + pData->currentDepth--; +} + + + + +BOOLEAN ReadInClothesStats(STR fileName) +{ + HWFILE hFile; + UINT32 uiBytesRead; + UINT32 uiFSize; + CHAR8 * lpcBuffer; + XML_Parser parser = XML_ParserCreate(NULL); + + clothesParseData pData; + + DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Loading Clothes.xml" ); + + // Open clothess 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, clothesStartElementHandle, clothesEndElementHandle); + XML_SetCharacterDataHandler(parser, clothesCharacterDataHandle); + + + memset(&pData,0,sizeof(pData)); + pData.curArray = Clothes; + pData.maxArraySize = CLOTHES_MAX; + + XML_SetUserData(parser, &pData); + + + if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE)) + { + CHAR8 errorBuf[511]; + + sprintf(errorBuf, "XML Parser Error in Clothes.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 ); +} + +BOOLEAN WriteClothesStats() +{ + //DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"writeclothessstats"); + HWFILE hFile; + + //Debug code; make sure that what we got from the file is the same as what's there + // Open a new file + hFile = FileOpen( "TABLEDATA\\Clothes out.xml", FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE ); + if ( !hFile ) + return( FALSE ); + + { + UINT32 cnt; + + FilePrintf(hFile,"\r\n"); + for(cnt = 0; cnt < MAXITEMS; ++cnt) + { + FilePrintf(hFile,"\t\r\n"); + + FilePrintf(hFile,"\t\t%d\r\n", cnt ); + FilePrintf(hFile,"\t\t%d\r\n", Clothes[cnt].vest ); + FilePrintf(hFile,"\t\t%d\r\n", Clothes[cnt].pants ); + + FilePrintf(hFile,"\t\r\n"); + } + FilePrintf(hFile,"\r\n"); + } + FileClose( hFile ); + + return( TRUE ); +} diff --git a/Utils/XML_Items.cpp b/Utils/XML_Items.cpp index 19d0968d..c4a75839 100644 --- a/Utils/XML_Items.cpp +++ b/Utils/XML_Items.cpp @@ -277,7 +277,8 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at strcmp(name, "CrowbarModifier") == 0 || strcmp(name, "DisarmModifier") == 0 || strcmp(name, "RepairModifier") == 0 || - strcmp(name, "usActionItemFlag") == 0 )) + strcmp(name, "usActionItemFlag") == 0 || + strcmp(name, "clothestype") == 0 )) { pData->curElement = ELEMENT_PROPERTY; //DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("itemStartElementHandle: going into element, name = %s",name) ); @@ -1393,6 +1394,11 @@ itemEndElementHandle(void *userData, const XML_Char *name) pData->curElement = ELEMENT; pData->curItem.usActionItemFlag = (UINT32) atol(pData->szCharData); } + else if(strcmp(name, "clothestype") == 0) + { + pData->curElement = ELEMENT; + pData->curItem.clothestype = (UINT32) atol(pData->szCharData); + } pData->maxReadDepth--; } @@ -2021,12 +2027,13 @@ BOOLEAN WriteItemStats() FilePrintf(hFile, "\t\t%d\r\n", Item[cnt].RepairModifier ); // Flugente poison system - FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].bPoisonPercentage ); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].bPoisonPercentage ); FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].usDamageChance ); FilePrintf(hFile,"\t\t%4.2f\r\n", Item[cnt].dirtIncreaseFactor ); FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].usActionItemFlag ); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].clothestype ); FilePrintf(hFile,"\t\r\n"); } diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index fd1d6dae..4c167d27 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -2900,7 +2900,7 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = L"Health: %d/%d\nPoison: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s", // added by Flugente: selection of a function to call in tactical - L"1 - Fill Canteens 2 - Clean one gun 3 - Clean all guns 4 - Nothing", + L"1 - Fill Canteens 2 - Clean one gun 3 - Clean all guns 4 - Take off clothes", // added by Flugente: decide what to do with the corpses L"1 - Decapitate 2 - Gut 3 - Take Clothes 4 - Take Body",