New feature: Covert ops

- you can disguise members of your team as civilians or soldiers and, if careful, avoid detection by the enemy.
- For more info, see http://www.bears-pit.com/board/ubbthreads.php/topics/309312/New_feature_Covert_operations.html#Post309312
- GameDir revision >= 1529 is needed for this feature

- fixed a bug that could cause inventory items to be treated like armed bombs
- bloodcats can now be skinned

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5529 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2012-08-24 23:52:55 +00:00
parent fa1586b22b
commit fd445fe5ed
62 changed files with 2151 additions and 263 deletions
+7
View File
@@ -2142,6 +2142,12 @@ void LoadSkillTraitsExternalSettings()
gSkillTraitValues.fSCPreventsBloodcatsAmbushes = iniReader.ReadBoolean("Scouting","PREVENTS_BLOODCATS_AMBUSHES", TRUE);
gSkillTraitValues.fSCThrowMessageIfAmbushPrevented = iniReader.ReadBoolean("Scouting","SHOW_MESSAGE_IF_AMBUSH_PREVENTED", TRUE);
// 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.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);
}
//DBrot: Grids
void LoadModSettings(){
@@ -2441,6 +2447,7 @@ void LoadGameAPBPConstants()
APBPConstants[AP_EAT] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_EAT",80),80);
APBPConstants[AP_CLEANINGKIT] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_CLEANINGKIT",80),80);
APBPConstants[AP_INVENTORY_EXPLOSIVE_ACTIVATE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_INVENTORY_EXPLOSIVE_ACTIVATE",20),20);
APBPConstants[AP_DISGUISE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_DISGUISE",80),80);
SetupMaxActionPointsAnimation();
#undef ReadInteger
+7
View File
@@ -1418,6 +1418,13 @@ typedef struct
BOOLEAN fSCPreventsBloodcatsAmbushes;
BOOLEAN fSCThrowMessageIfAmbushPrevented;
// COVERT OPS
INT16 sCOMeleeCTHBonus;
INT16 sCoMeleeInstakillBonus;
INT16 sCODisguiseAPReduction;
INT16 sCOCloseDetectionRange;
INT16 sCOCloseDetectionRangeSoldierCorpse;
} SKILL_TRAIT_VALUES;
// HEADROCK HAM 4: Constants used as coefficients by the various parts of the new CTH system.
+1
View File
@@ -201,6 +201,7 @@ AP_FORTIFICATION,
AP_EAT,
AP_CLEANINGKIT,
AP_INVENTORY_EXPLOSIVE_ACTIVATE,
AP_DISGUISE,
TOTAL_APBP_VALUES
};
#endif
+12 -2
View File
@@ -731,6 +731,17 @@ void GiveItemsToPC( UINT8 ubProfileId )
GiveIMPRandomItems(pProfile, IMP_DOCTOR);
}
}
if (PROFILE_HAS_SKILL_TRAIT(ubProfileId, COVERT_NT))
{
if( gGameExternalOptions.fExpertsGetDifferentChoices && PROFILE_HAS_EXPERT_TRAIT(ubProfileId, COVERT_NT))
{
GiveIMPRandomItems(pProfile,IMP_COVERT_EXP);
}
else
{
GiveIMPRandomItems(pProfile, IMP_COVERT);
}
}
// MINOR TRAITS
if (PROFILE_HAS_SKILL_TRAIT(ubProfileId, AMBIDEXTROUS_NT))
{
@@ -771,8 +782,7 @@ void GiveItemsToPC( UINT8 ubProfileId )
if (PROFILE_HAS_SKILL_TRAIT(ubProfileId, SCOUTING_NT))
{
GiveIMPRandomItems(pProfile,IMP_SCOUTING);
}
}
}
else
{
+60 -8
View File
@@ -62,6 +62,7 @@
#define IMP_SKILL_TRAIT__GREY_BOX_OFFSET_X 5
#define IMP_SKILL_TRAIT__GREY_BOX_OFFSET_Y 7
#define NEWTRAIT_EXPERT_OFFSET 12 // Flugente: offset between normal and expert trait strings
//*******************************************************************
//
@@ -858,7 +859,7 @@ void IMPSkillTraitDisplaySkills()
if( gGameOptions.fNewTraitSystem )
{
if ( gfSkillTraitQuestions[ uiCnt ] && gfSkillTraitQuestions2[ uiCnt ] && uiCnt != IMP_SKILL_TRAITS_NEW_MAJOR_NONE )
DrawTextToScreen( gzIMPSkillTraitsTextNewMajor[ uiCnt+11 ], usPosX, usPosY, 0, IMP_SKILL_TRAIT__FONT, IMP_SKILL_TRAIT__COLOR, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED );
DrawTextToScreen( gzIMPSkillTraitsTextNewMajor[ uiCnt+12 ], usPosX, usPosY, 0, IMP_SKILL_TRAIT__FONT, IMP_SKILL_TRAIT__COLOR, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED );
else
DrawTextToScreen( gzIMPSkillTraitsTextNewMajor[ uiCnt ], usPosX, usPosY, 0, IMP_SKILL_TRAIT__FONT, IMP_SKILL_TRAIT__COLOR, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED );
}
@@ -1075,6 +1076,10 @@ void AddSelectedSkillsToSkillsList()
AddSkillToSkillList( DOCTOR_NT );
break;
case IMP_SKILL_TRAITS_NEW_COVERT:
AddSkillToSkillList( COVERT_NT );
break;
default:
break;
}
@@ -1190,6 +1195,10 @@ void AddSelectedSkillsToSkillsList()
AddSkillToSkillList( DOCTOR_NT );
break;
case IMP_SKILL_TRAITS_NEW_COVERT:
AddSkillToSkillList( COVERT_NT );
break;
default:
break;
}
@@ -1560,6 +1569,13 @@ INT32 LeadershipRequiredDueToMajorSkills( void )
else
return (35);
}
else if (gfSkillTraitQuestions[ IMP_SKILL_TRAITS_NEW_COVERT ])
{
if (gfSkillTraitQuestions2[ IMP_SKILL_TRAITS_NEW_COVERT ])
return (45);
else
return (30);
}
// Check the second skill trait
else if (gfSkillTraitQuestions2[ IMP_SKILL_TRAITS_NEW_SQUADLEADER ])
{
@@ -1588,6 +1604,13 @@ INT32 WisdomRequiredDueToMajorSkills( void )
else
return (60);
}
else if (gfSkillTraitQuestions[ IMP_SKILL_TRAITS_NEW_COVERT ])
{
if (gfSkillTraitQuestions2[ IMP_SKILL_TRAITS_NEW_COVERT ])
return (70);
else
return (65);
}
else if (gfSkillTraitQuestions[ IMP_SKILL_TRAITS_NEW_HEAVY_WEAPONS ])
{
if (gfSkillTraitQuestions2[ IMP_SKILL_TRAITS_NEW_HEAVY_WEAPONS ])
@@ -2186,7 +2209,7 @@ void AssignSkillTraitHelpText( UINT8 ubTraitNumber, BOOLEAN fExpertLevel )
}
if( gSkillTraitValues.ubSLEffectiveLevelInRadius != 0 )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsSquadleader[1], ( gSkillTraitValues.ubSLEffectiveLevelInRadius * (fExpertLevel ? 2 : 1)), (fExpertLevel ? gzIMPSkillTraitsTextNewMajor[ubTraitNumber + 11] : gzIMPSkillTraitsTextNewMajor[ubTraitNumber]));
swprintf( atStr, gzIMPMajorTraitsHelpTextsSquadleader[1], ( gSkillTraitValues.ubSLEffectiveLevelInRadius * (fExpertLevel ? 2 : 1)), (fExpertLevel ? gzIMPSkillTraitsTextNewMajor[ubTraitNumber + NEWTRAIT_EXPERT_OFFSET] : gzIMPSkillTraitsTextNewMajor[ubTraitNumber]));
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubSLEffectiveLevelAsStandby != 0 )
@@ -2201,7 +2224,7 @@ void AssignSkillTraitHelpText( UINT8 ubTraitNumber, BOOLEAN fExpertLevel )
}
if( gSkillTraitValues.ubSLOverallSuppresionBonusPercent != 0 )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsSquadleader[3], ( gSkillTraitValues.ubSLOverallSuppresionBonusPercent * (fExpertLevel ? 2 : 1)), L"%", (fExpertLevel ? gzIMPSkillTraitsTextNewMajor[ubTraitNumber + 11] : gzIMPSkillTraitsTextNewMajor[ubTraitNumber]));
swprintf( atStr, gzIMPMajorTraitsHelpTextsSquadleader[3], ( gSkillTraitValues.ubSLOverallSuppresionBonusPercent * (fExpertLevel ? 2 : 1)), L"%", (fExpertLevel ? gzIMPSkillTraitsTextNewMajor[ubTraitNumber + NEWTRAIT_EXPERT_OFFSET] : gzIMPSkillTraitsTextNewMajor[ubTraitNumber]));
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubSLMoraleGainBonus != 0 )
@@ -2231,12 +2254,12 @@ void AssignSkillTraitHelpText( UINT8 ubTraitNumber, BOOLEAN fExpertLevel )
if( gSkillTraitValues.ubSLFearResistance != 0 )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsSquadleader[9], ( gSkillTraitValues.ubSLFearResistance * (fExpertLevel ? 2 : 1)), L"%", (fExpertLevel ? gzIMPSkillTraitsTextNewMajor[ubTraitNumber + 11] : gzIMPSkillTraitsTextNewMajor[ubTraitNumber]));
swprintf( atStr, gzIMPMajorTraitsHelpTextsSquadleader[9], ( gSkillTraitValues.ubSLFearResistance * (fExpertLevel ? 2 : 1)), L"%", (fExpertLevel ? gzIMPSkillTraitsTextNewMajor[ubTraitNumber + NEWTRAIT_EXPERT_OFFSET] : gzIMPSkillTraitsTextNewMajor[ubTraitNumber]));
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubSLDeathMoralelossMultiplier != 0 )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsSquadleader[10], (1 + ( gSkillTraitValues.ubSLDeathMoralelossMultiplier * (fExpertLevel ? 2 : 1))), (fExpertLevel ? gzIMPSkillTraitsTextNewMajor[ubTraitNumber + 11] : gzIMPSkillTraitsTextNewMajor[ubTraitNumber]));
swprintf( atStr, gzIMPMajorTraitsHelpTextsSquadleader[10], (1 + ( gSkillTraitValues.ubSLDeathMoralelossMultiplier * (fExpertLevel ? 2 : 1))), (fExpertLevel ? gzIMPSkillTraitsTextNewMajor[ubTraitNumber + NEWTRAIT_EXPERT_OFFSET] : gzIMPSkillTraitsTextNewMajor[ubTraitNumber]));
wcscat( apStr, atStr );
}
break;
@@ -2281,17 +2304,17 @@ void AssignSkillTraitHelpText( UINT8 ubTraitNumber, BOOLEAN fExpertLevel )
}
if( gSkillTraitValues.ubTECtHControlledRobotBonus != 0 )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsTechnician[7], ( gSkillTraitValues.ubTECtHControlledRobotBonus * (fExpertLevel ? 2 : 1)), L"%", (fExpertLevel ? gzIMPSkillTraitsTextNewMajor[ubTraitNumber + 11] : gzIMPSkillTraitsTextNewMajor[ubTraitNumber]));
swprintf( atStr, gzIMPMajorTraitsHelpTextsTechnician[7], ( gSkillTraitValues.ubTECtHControlledRobotBonus * (fExpertLevel ? 2 : 1)), L"%", (fExpertLevel ? gzIMPSkillTraitsTextNewMajor[ubTraitNumber + NEWTRAIT_EXPERT_OFFSET] : gzIMPSkillTraitsTextNewMajor[ubTraitNumber]));
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubTETraitsNumToRepairRobot == 2 )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsTechnician[8], (fExpertLevel ? gzIMPSkillTraitsTextNewMajor[ubTraitNumber + 11] : gzIMPSkillTraitsTextNewMajor[ubTraitNumber]));
swprintf( atStr, gzIMPMajorTraitsHelpTextsTechnician[8], (fExpertLevel ? gzIMPSkillTraitsTextNewMajor[ubTraitNumber + NEWTRAIT_EXPERT_OFFSET] : gzIMPSkillTraitsTextNewMajor[ubTraitNumber]));
wcscat( apStr, atStr );
}
else if( gSkillTraitValues.ubTETraitsNumToRepairRobot == 1 )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsTechnician[8], (fExpertLevel ? gzIMPSkillTraitsTextNewMajor[ubTraitNumber + 11] : gzIMPSkillTraitsTextNewMajor[ubTraitNumber]));
swprintf( atStr, gzIMPMajorTraitsHelpTextsTechnician[8], (fExpertLevel ? gzIMPSkillTraitsTextNewMajor[ubTraitNumber + NEWTRAIT_EXPERT_OFFSET] : gzIMPSkillTraitsTextNewMajor[ubTraitNumber]));
wcscat( apStr, atStr );
if( gSkillTraitValues.ubTERepairRobotPenaltyReduction != 0 && fExpertLevel)
@@ -2353,6 +2376,35 @@ void AssignSkillTraitHelpText( UINT8 ubTraitNumber, BOOLEAN fExpertLevel )
}
break;
}
case IMP_SKILL_TRAITS_NEW_COVERT:
{
swprintf( apStr, L"" );
swprintf( atStr, gzIMPMajorTraitsHelpTextsCovertOps[0]);
wcscat( apStr, atStr );
swprintf( atStr, gzIMPMajorTraitsHelpTextsCovertOps[1]);
wcscat( apStr, atStr );
if ( !fExpertLevel )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsCovertOps[2], gSkillTraitValues.sCOCloseDetectionRange);
wcscat( apStr, atStr );
}
swprintf( atStr, gzIMPMajorTraitsHelpTextsCovertOps[3], gSkillTraitValues.sCOCloseDetectionRangeSoldierCorpse);
wcscat( apStr, atStr );
swprintf( atStr, gzIMPMajorTraitsHelpTextsCovertOps[4], ( gSkillTraitValues.sCOMeleeCTHBonus * (fExpertLevel ? 2 : 1)), L"%");
wcscat( apStr, atStr );
swprintf( atStr, gzIMPMajorTraitsHelpTextsCovertOps[5], ( gSkillTraitValues.sCoMeleeInstakillBonus * (fExpertLevel ? 2 : 1)), L"%");
wcscat( apStr, atStr );
INT16 apreduction = ( gSkillTraitValues.sCODisguiseAPReduction * (fExpertLevel ? 2 : 1));
swprintf( atStr, gzIMPMajorTraitsHelpTextsCovertOps[6], apreduction, L"%");
wcscat( apStr, atStr );
break;
}
case IMP_SKILL_TRAITS_NEW_MAJOR_NONE:
{
swprintf( apStr, gzIMPMajorTraitsHelpTextsNone[0] );
+1
View File
@@ -41,6 +41,7 @@ enum
IMP_SKILL_TRAITS_NEW_SQUADLEADER,
IMP_SKILL_TRAITS_NEW_TECHNICIAN,
IMP_SKILL_TRAITS_NEW_DOCTOR,
IMP_SKILL_TRAITS_NEW_COVERT,
IMP_SKILL_TRAITS_NEW_MAJOR_NONE,
IMP_SKILL_TRAITS_NEW_NUMBER_MAJOR_SKILLS,
};
+6
View File
@@ -4650,6 +4650,12 @@ void HandleIMPCharProfileResultsMessage( void)
wcscpy(pString, MissingIMPSkillsDescriptions[10]);
AddEmailRecordToList( pString );
}
// Covert ops
if ( ProfileHasSkillTrait( iCurrentIMPSlot, COVERT_NT ) > 0 )
{
wcscpy(pString, MissingIMPSkillsDescriptions[11]);
AddEmailRecordToList( pString );
}
}
else
{
+64 -13
View File
@@ -1769,7 +1769,7 @@ void DisplayCharStats(INT32 iId, INT32 iSlot)
{
if ( ProfileHasSkillTrait( Menptr[iId].ubProfile, ubCnt ) == 2 )
{
ubTempSkillArray[bNumSkillTraits] = (ubCnt + 19);
ubTempSkillArray[bNumSkillTraits] = (ubCnt + NEWTRAIT_MERCSKILL_EXPERTOFFSET);
bNumSkillTraits++;
}
else if ( ProfileHasSkillTrait( Menptr[iId].ubProfile, ubCnt ) == 1 )
@@ -1816,9 +1816,18 @@ void DisplayCharStats(INT32 iId, INT32 iSlot)
}
else
{
swprintf( sString, L"%s", gzMercSkillTextNew[ ubTempSkillArray[ubCnt] ] );
// Flugente: as the whole trait display is fubar, we have to to a special treatment here for new traits
UINT8 display1 = ubTempSkillArray[ubCnt];
if ( display1 > SCOUTING_NT + NEWTRAIT_MERCSKILL_EXPERTOFFSET )
display1 -= NUM_MINOR_TRAITS;
else if ( display1 >= AMBIDEXTROUS_NT && display1 <= SCOUTING_NT )
display1++;
else if ( display1 == NEWTRAIT_MERCSKILL_EXPERTOFFSET )
display1 -= NUM_MINOR_TRAITS;
swprintf( sString, L"%s", gzMercSkillTextNew[ display1 ] );
if ( ubTempSkillArray[ubCnt] > 19 )
if ( ubTempSkillArray[ubCnt] > NEWTRAIT_MERCSKILL_EXPERTOFFSET )
{
FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[19].x+(iSlot*TEXT_BOX_WIDTH)),0,TEXT_BOX_WIDTH-20,0,sString, FONT10ARIALBOLD, &sX, &sY);
@@ -1857,15 +1866,28 @@ void DisplayCharStats(INT32 iId, INT32 iSlot)
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, NULL );
MSYS_AddRegion( &gSkillTraitHelpTextRegion[ubCnt] );
fAddedTraitRegion[ubCnt] = TRUE;
// Assign the text
AssignPersonnelSkillTraitHelpText( ((ubTempSkillArray[ubCnt] > 19) ? (ubTempSkillArray[ubCnt]-19) : ubTempSkillArray[ubCnt]), ((ubTempSkillArray[ubCnt] > 19) ? TRUE : FALSE), Menptr[iId].ubProfile, ubCnt );
// Assign the text
UINT8 traitnr = ubTempSkillArray[ubCnt];
UINT8 mlas = NEWTRAIT_MERCSKILL_EXPERTOFFSET;
if ( traitnr > mlas )
{
traitnr = traitnr - mlas;
}
// Flugente: as the whole trait display is fubar, we have to to a special treatment here for new traits
UINT8 display2 = ubTempSkillArray[ubCnt];
if ( display2 == NUM_MAJOR_TRAITS )
display2 += NUM_MINOR_TRAITS;
AssignPersonnelSkillTraitHelpText( traitnr, ((ubTempSkillArray[ubCnt] > NEWTRAIT_MERCSKILL_EXPERTOFFSET) ? TRUE : FALSE), Menptr[iId].ubProfile, ubCnt );
}
}
// if we have more skills than we can display, show "more" and create a tooltip box with the rest of them
if ( fDisplayMoreTraits )
{
swprintf( sString, L"%s", gzMercSkillTextNew[ 29 ]); // dispaly "More..."
swprintf( sString, L"%s", gzMercSkillTextNew[ NEWTRAIT_MERCSKILL_OFFSET_ALL + 1 ]); // dispaly "More..."
FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[19].x+(iSlot*TEXT_BOX_WIDTH)),0,TEXT_BOX_WIDTH-20,0,sString, PERS_FONT, &sX, &sY);
if( sX <= iMinimumX )
{
@@ -7444,7 +7466,7 @@ void AssignPersonnelSkillTraitHelpText( UINT8 ubTraitNumber, BOOLEAN fExpertLeve
}
if( gSkillTraitValues.ubSLEffectiveLevelInRadius != 0 )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsSquadleader[1], ( gSkillTraitValues.ubSLEffectiveLevelInRadius * (fExpertLevel ? 2 : 1)), (fExpertLevel ? gzMercSkillTextNew[ubTraitNumber + 19] : gzMercSkillTextNew[ubTraitNumber]));
swprintf( atStr, gzIMPMajorTraitsHelpTextsSquadleader[1], ( gSkillTraitValues.ubSLEffectiveLevelInRadius * (fExpertLevel ? 2 : 1)), (fExpertLevel ? gzMercSkillTextNew[ubTraitNumber + NEWTRAIT_MERCSKILL_EXPERTOFFSET] : gzMercSkillTextNew[ubTraitNumber]));
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubSLEffectiveLevelAsStandby != 0 )
@@ -7459,7 +7481,7 @@ void AssignPersonnelSkillTraitHelpText( UINT8 ubTraitNumber, BOOLEAN fExpertLeve
}
if( gSkillTraitValues.ubSLOverallSuppresionBonusPercent != 0 )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsSquadleader[3], ( gSkillTraitValues.ubSLOverallSuppresionBonusPercent * (fExpertLevel ? 2 : 1)), L"%", (fExpertLevel ? gzMercSkillTextNew[ubTraitNumber + 19] : gzMercSkillTextNew[ubTraitNumber]));
swprintf( atStr, gzIMPMajorTraitsHelpTextsSquadleader[3], ( gSkillTraitValues.ubSLOverallSuppresionBonusPercent * (fExpertLevel ? 2 : 1)), L"%", (fExpertLevel ? gzMercSkillTextNew[ubTraitNumber + NEWTRAIT_MERCSKILL_EXPERTOFFSET] : gzMercSkillTextNew[ubTraitNumber]));
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubSLMoraleGainBonus != 0 )
@@ -7489,12 +7511,12 @@ void AssignPersonnelSkillTraitHelpText( UINT8 ubTraitNumber, BOOLEAN fExpertLeve
if( gSkillTraitValues.ubSLFearResistance != 0 )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsSquadleader[9], ( gSkillTraitValues.ubSLFearResistance * (fExpertLevel ? 2 : 1)), L"%", (fExpertLevel ? gzMercSkillTextNew[ubTraitNumber + 19] : gzMercSkillTextNew[ubTraitNumber]));
swprintf( atStr, gzIMPMajorTraitsHelpTextsSquadleader[9], ( gSkillTraitValues.ubSLFearResistance * (fExpertLevel ? 2 : 1)), L"%", (fExpertLevel ? gzMercSkillTextNew[ubTraitNumber + NEWTRAIT_MERCSKILL_EXPERTOFFSET] : gzMercSkillTextNew[ubTraitNumber]));
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubSLDeathMoralelossMultiplier != 0 )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsSquadleader[10], (1 + ( gSkillTraitValues.ubSLDeathMoralelossMultiplier * (fExpertLevel ? 2 : 1))), (fExpertLevel ? gzMercSkillTextNew[ubTraitNumber + 19] : gzMercSkillTextNew[ubTraitNumber]));
swprintf( atStr, gzIMPMajorTraitsHelpTextsSquadleader[10], (1 + ( gSkillTraitValues.ubSLDeathMoralelossMultiplier * (fExpertLevel ? 2 : 1))), (fExpertLevel ? gzMercSkillTextNew[ubTraitNumber + NEWTRAIT_MERCSKILL_EXPERTOFFSET] : gzMercSkillTextNew[ubTraitNumber]));
wcscat( apStr, atStr );
}
break;
@@ -7539,17 +7561,17 @@ void AssignPersonnelSkillTraitHelpText( UINT8 ubTraitNumber, BOOLEAN fExpertLeve
}
if( gSkillTraitValues.ubTECtHControlledRobotBonus != 0 )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsTechnician[7], ( gSkillTraitValues.ubTECtHControlledRobotBonus * (fExpertLevel ? 2 : 1)), L"%", (fExpertLevel ? gzMercSkillTextNew[ubTraitNumber + 19] : gzMercSkillTextNew[ubTraitNumber]));
swprintf( atStr, gzIMPMajorTraitsHelpTextsTechnician[7], ( gSkillTraitValues.ubTECtHControlledRobotBonus * (fExpertLevel ? 2 : 1)), L"%", (fExpertLevel ? gzMercSkillTextNew[ubTraitNumber + NEWTRAIT_MERCSKILL_EXPERTOFFSET] : gzMercSkillTextNew[ubTraitNumber]));
wcscat( apStr, atStr );
}
if( gSkillTraitValues.ubTETraitsNumToRepairRobot == 2 )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsTechnician[8], (fExpertLevel ? gzMercSkillTextNew[ubTraitNumber + 19] : gzMercSkillTextNew[ubTraitNumber]));
swprintf( atStr, gzIMPMajorTraitsHelpTextsTechnician[8], (fExpertLevel ? gzMercSkillTextNew[ubTraitNumber + NEWTRAIT_MERCSKILL_EXPERTOFFSET] : gzMercSkillTextNew[ubTraitNumber]));
wcscat( apStr, atStr );
}
else if( gSkillTraitValues.ubTETraitsNumToRepairRobot == 1 )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsTechnician[8], (fExpertLevel ? gzMercSkillTextNew[ubTraitNumber + 19] : gzMercSkillTextNew[ubTraitNumber]));
swprintf( atStr, gzIMPMajorTraitsHelpTextsTechnician[8], (fExpertLevel ? gzMercSkillTextNew[ubTraitNumber + NEWTRAIT_MERCSKILL_EXPERTOFFSET] : gzMercSkillTextNew[ubTraitNumber]));
wcscat( apStr, atStr );
if( gSkillTraitValues.ubTERepairRobotPenaltyReduction != 0 && fExpertLevel)
@@ -7983,6 +8005,35 @@ void AssignPersonnelSkillTraitHelpText( UINT8 ubTraitNumber, BOOLEAN fExpertLeve
}
break;
}
case COVERT_NT:
{
swprintf( apStr, L"" );
swprintf( atStr, gzIMPMajorTraitsHelpTextsCovertOps[0]);
wcscat( apStr, atStr );
swprintf( atStr, gzIMPMajorTraitsHelpTextsCovertOps[1]);
wcscat( apStr, atStr );
if ( !fExpertLevel )
{
swprintf( atStr, gzIMPMajorTraitsHelpTextsCovertOps[2], gSkillTraitValues.sCOCloseDetectionRange);
wcscat( apStr, atStr );
}
swprintf( atStr, gzIMPMajorTraitsHelpTextsCovertOps[3], gSkillTraitValues.sCOCloseDetectionRangeSoldierCorpse);
wcscat( apStr, atStr );
swprintf( atStr, gzIMPMajorTraitsHelpTextsCovertOps[4], ( gSkillTraitValues.sCOMeleeCTHBonus * (fExpertLevel ? 2 : 1)), L"%");
wcscat( apStr, atStr );
swprintf( atStr, gzIMPMajorTraitsHelpTextsCovertOps[5], ( gSkillTraitValues.sCoMeleeInstakillBonus * (fExpertLevel ? 2 : 1)), L"%");
wcscat( apStr, atStr );
INT16 apreduction = ( gSkillTraitValues.sCODisguiseAPReduction * (fExpertLevel ? 2 : 1));
swprintf( atStr, gzIMPMajorTraitsHelpTextsCovertOps[6], apreduction, L"%");
wcscat( apStr, atStr );
break;
}
case NO_SKILLTRAIT_NT:
{
swprintf( apStr, L"" );
+16 -16
View File
@@ -5,17 +5,17 @@
// Message box flags
#define MSG_BOX_FLAG_USE_CENTERING_RECT 0x0001 // Pass in a rect to center in
#define MSG_BOX_FLAG_OK 0x0002 // Displays OK button
#define MSG_BOX_FLAG_YESNO 0x0004 // Displays YES NO buttons
#define MSG_BOX_FLAG_CANCEL 0x0008 // Displays YES NO buttons
#define MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS 0x0010 // Displays four numbered buttons, 1-4
#define MSG_BOX_FLAG_YESNOCONTRACT 0x0020 // yes no and contract buttons
#define MSG_BOX_FLAG_OKCONTRACT 0x0040 // ok and contract buttons
#define MSG_BOX_FLAG_YESNOLIE 0x0080 // ok and contract buttons
#define MSG_BOX_FLAG_CONTINUESTOP 0x0100 // continue stop box
#define MSG_BOX_FLAG_OKSKIP 0x0200 // Displays ok or skip (meanwhile) buttons
#define MSG_BOX_FLAG_GENERICCONTRACT 0x0400 // displays contract buttoin + 2 user-defined text buttons
#define MSG_BOX_FLAG_GENERIC 0x0800 // 2 user-defined text buttons
#define MSG_BOX_FLAG_OK 0x0002 // Displays OK button
#define MSG_BOX_FLAG_YESNO 0x0004 // Displays YES NO buttons
#define MSG_BOX_FLAG_CANCEL 0x0008 // Displays YES NO buttons
#define MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS 0x0010 // Displays four numbered buttons, 1-4
#define MSG_BOX_FLAG_YESNOCONTRACT 0x0020 // yes no and contract buttons
#define MSG_BOX_FLAG_OKCONTRACT 0x0040 // ok and contract buttons
#define MSG_BOX_FLAG_YESNOLIE 0x0080 // ok and contract buttons
#define MSG_BOX_FLAG_CONTINUESTOP 0x0100 // continue stop box
#define MSG_BOX_FLAG_OKSKIP 0x0200 // Displays ok or skip (meanwhile) buttons
#define MSG_BOX_FLAG_GENERICCONTRACT 0x0400 // displays contract buttoin + 2 user-defined text buttons
#define MSG_BOX_FLAG_GENERIC 0x0800 // 2 user-defined text buttons
// OJW - Adding text chatbox
#define MSG_BOX_FLAG_INPUTBOX 0x1000 // has a text input field
// Flugente - added boxes for simultaneous defuse/detonate mechanism
@@ -23,11 +23,11 @@
#define MSG_BOX_FLAG_SIXTEEN_NUMBERED_BUTTONS 0x4000 // Displays sixteen numbered buttons, 1-16, for setting up a tripwire network and choosing both a detonation and defusing frequency
// message box return codes
#define MSG_BOX_RETURN_OK 1 // ENTER or on OK button
#define MSG_BOX_RETURN_YES 2 // ENTER or YES button
#define MSG_BOX_RETURN_NO 3 // ESC, Right Click or NO button
#define MSG_BOX_RETURN_CONTRACT 4 // contract button
#define MSG_BOX_RETURN_LIE 5 // LIE BUTTON
#define MSG_BOX_RETURN_OK 1 // ENTER or on OK button
#define MSG_BOX_RETURN_YES 2 // ENTER or YES button
#define MSG_BOX_RETURN_NO 3 // ESC, Right Click or NO button
#define MSG_BOX_RETURN_CONTRACT 4 // contract button
#define MSG_BOX_RETURN_LIE 5 // LIE BUTTON
// message box style flags
enum
+37 -25
View File
@@ -45,8 +45,9 @@ typedef struct
CHAR16 szCurDetailedUnexploredName[MAX_SECTOR_NAME_LENGTH];
CHAR16 szCurExploredName[MAX_SECTOR_NAME_LENGTH];
CHAR16 szCurDetailedExploredName[MAX_SECTOR_NAME_LENGTH];
UINT8 sWaterType;
UINT16 usNaturalDirt;
UINT8 sWaterType; // Food System
UINT16 usNaturalDirt; // Dirt System
UINT8 usCurfewValue; // Covert Ops
UINT32 currentDepth;
UINT32 maxReadDepth;
} SectorNameParseData;
@@ -80,7 +81,12 @@ SectorNameStartElementHandle(void *userData, const XML_Char *name, const char **
SectorExternalData[x][1].usNaturalDirt = 0;
SectorExternalData[x][2].usNaturalDirt = 0;
SectorExternalData[x][3].usNaturalDirt = 0;
SectorExternalData[x][0].usCurfewValue = 0;
SectorExternalData[x][1].usCurfewValue = 0;
SectorExternalData[x][2].usCurfewValue = 0;
SectorExternalData[x][3].usCurfewValue = 0;
if (Sector_Level == 0 )
{
gzSectorNames[x][0][0]=0;
@@ -128,7 +134,8 @@ SectorNameStartElementHandle(void *userData, const XML_Char *name, const char **
strcmp(name, "szExploredName") == 0 ||
strcmp(name, "szDetailedExploredName") == 0 ||
strcmp(name, "sWaterType") == 0 ||
strcmp(name, "usNaturalDirt") == 0 ))
strcmp(name, "usNaturalDirt") == 0 ||
strcmp(name, "usCurfewValue") == 0 ))
{
pData->curElement = SECTORNAME_ELEMENT;
@@ -180,16 +187,6 @@ SectorNameEndElementHandle(void *userData, const XML_Char *name)
wcscpy(gzSectorNames[ubSectorId][1], pData->szCurDetailedUnexploredName);
wcscpy(gzSectorNames[ubSectorId][2], pData->szCurExploredName);
wcscpy(gzSectorNames[ubSectorId][3], pData->szCurDetailedExploredName);
SectorExternalData[ubSectorId][0].usWaterType = pData->sWaterType;
SectorExternalData[ubSectorId][1].usWaterType = pData->sWaterType;
SectorExternalData[ubSectorId][2].usWaterType = pData->sWaterType;
SectorExternalData[ubSectorId][3].usWaterType = pData->sWaterType;
SectorExternalData[ubSectorId][0].usNaturalDirt = pData->usNaturalDirt;
SectorExternalData[ubSectorId][1].usNaturalDirt = pData->usNaturalDirt;
SectorExternalData[ubSectorId][2].usNaturalDirt = pData->usNaturalDirt;
SectorExternalData[ubSectorId][3].usNaturalDirt = pData->usNaturalDirt;
}
// moved to lua
//else if (Sector_Level == 1 )
@@ -221,17 +218,7 @@ SectorNameEndElementHandle(void *userData, const XML_Char *name)
wcscpy(gzSectorNames[ubSectorId][0], pData->szCurUnexploredName);
wcscpy(gzSectorNames[ubSectorId][1], pData->szCurDetailedUnexploredName);
wcscpy(gzSectorNames[ubSectorId][2], pData->szCurExploredName);
wcscpy(gzSectorNames[ubSectorId][3], pData->szCurDetailedExploredName);
SectorExternalData[ubSectorId][0].usWaterType = pData->sWaterType;
SectorExternalData[ubSectorId][1].usWaterType = pData->sWaterType;
SectorExternalData[ubSectorId][2].usWaterType = pData->sWaterType;
SectorExternalData[ubSectorId][3].usWaterType = pData->sWaterType;
SectorExternalData[ubSectorId][0].usNaturalDirt = pData->usNaturalDirt;
SectorExternalData[ubSectorId][1].usNaturalDirt = pData->usNaturalDirt;
SectorExternalData[ubSectorId][2].usNaturalDirt = pData->usNaturalDirt;
SectorExternalData[ubSectorId][3].usNaturalDirt = pData->usNaturalDirt;
wcscpy(gzSectorNames[ubSectorId][3], pData->szCurDetailedExploredName);
}
// moved to lua
//else if (Sector_Level == 1 )
@@ -256,6 +243,26 @@ SectorNameEndElementHandle(void *userData, const XML_Char *name)
// wcscpy(gzSectorUndergroundNames3[ubSectorId][3], pData->szCurDetailedExploredName);
//}
}
SectorExternalData[ubSectorId][0].usWaterType = pData->sWaterType;
SectorExternalData[ubSectorId][1].usWaterType = pData->sWaterType;
SectorExternalData[ubSectorId][2].usWaterType = pData->sWaterType;
SectorExternalData[ubSectorId][3].usWaterType = pData->sWaterType;
SectorExternalData[ubSectorId][0].usNaturalDirt = pData->usNaturalDirt;
SectorExternalData[ubSectorId][1].usNaturalDirt = pData->usNaturalDirt;
SectorExternalData[ubSectorId][2].usNaturalDirt = pData->usNaturalDirt;
SectorExternalData[ubSectorId][3].usNaturalDirt = pData->usNaturalDirt;
SectorExternalData[ubSectorId][0].usCurfewValue = pData->usCurfewValue;
SectorExternalData[ubSectorId][1].usCurfewValue = pData->usCurfewValue;
SectorExternalData[ubSectorId][2].usCurfewValue = pData->usCurfewValue;
SectorExternalData[ubSectorId][3].usCurfewValue = pData->usCurfewValue;
// clean up values afterwards
pData->sWaterType = 0;
pData->usNaturalDirt = 100;
pData->usCurfewValue = 0;
}
}
@@ -315,6 +322,11 @@ SectorNameEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = SECTORNAME_ELEMENT_SECTOR;
pData->usNaturalDirt = (UINT16) atoi(pData->szCharData);
}
else if(strcmp(name, "usCurfewValue") == 0)
{
pData->curElement = SECTORNAME_ELEMENT_SECTOR;
pData->usCurfewValue = (UINT16) atoi(pData->szCharData);
}
pData->maxReadDepth--;
}
+46 -48
View File
@@ -387,67 +387,65 @@ void HandleEndTurnDrugAdjustments( SOLDIERTYPE *pSoldier )
}
// Flugente: always do the following checks. Thereby, if the effect runs out, our stats will be back to normal
// only do the checks for the player team, as soldiers do not have a gMercProfiles
if ( pSoldier->bTeam == gbPlayerNum)
//////////////// STRENGTH ////////////////
pSoldier->bExtraStrength = pSoldier->drugs.bDrugEffect[ DRUG_TYPE_STRENGTH ] - pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_STRENGTH ];
//////////////// DEXTERITY ////////////////
pSoldier->bExtraDexterity = pSoldier->drugs.bDrugEffect[ DRUG_TYPE_DEXTERITY ] - pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_DEXTERITY ];
//////////////// AGILITY ////////////////
pSoldier->bExtraAgility = pSoldier->drugs.bDrugEffect[ DRUG_TYPE_AGILITY ] - pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_AGILITY ];
//////////////// WISDOM ////////////////
pSoldier->bExtraWisdom = pSoldier->drugs.bDrugEffect[ DRUG_TYPE_WISDOM ] - pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_WISDOM ];
// if our sideeffect count is 1 (which should occur a while AFTER we took the drug), we suddenly become blind for a few turns...
if ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_BLIND ] == 0 && pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_BLIND ] == 1 )
{
//////////////// STRENGTH ////////////////
pSoldier->bExtraStrength = pSoldier->drugs.bDrugEffect[ DRUG_TYPE_STRENGTH ] - pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_STRENGTH ];
pSoldier->bBlindedCounter = 3;
}
//////////////// DEXTERITY ////////////////
pSoldier->bExtraDexterity = pSoldier->drugs.bDrugEffect[ DRUG_TYPE_DEXTERITY ] - pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_DEXTERITY ];
// if our sideeffect count is 1 (which should occur a while AFTER we took the drug), we get a heart-attack and get knocked out...
if ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_KNOCKOUT ] == 0 && pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_KNOCKOUT ] == 1 )
{
// Keel over...
DeductPoints( pSoldier, 0, 20000 );
}
//////////////// AGILITY ////////////////
pSoldier->bExtraAgility = pSoldier->drugs.bDrugEffect[ DRUG_TYPE_AGILITY ] - pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_AGILITY ];
// if we have a life damaging effect, deduct life points
if ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_LIFEDAMAGE ] == 0 && pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_LIFEDAMAGE ] > 0 )
{
pSoldier->EVENT_SoldierGotHit( 0, 400, 0, pSoldier->ubDirection, 320, NOBODY , FIRE_WEAPON_NO_SPECIAL, pSoldier->bAimShotLocation, 0, -1 );
//////////////// WISDOM ////////////////
pSoldier->bExtraWisdom = pSoldier->drugs.bDrugEffect[ DRUG_TYPE_WISDOM ] - pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_WISDOM ];
// if our sideeffect count is 1 (which should occur a while AFTER we took the drug), we suddenly become blind for a few turns...
if ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_BLIND ] == 0 && pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_BLIND ] == 1 )
/*if ( pSoldier->stats.bLife > OKLIFE )
{
pSoldier->bBlindedCounter = 3;
}
// if our sideeffect count is 1 (which should occur a while AFTER we took the drug), we get a heart-attack and get knocked out...
if ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_KNOCKOUT ] == 0 && pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_KNOCKOUT ] == 1 )
{
// Keel over...
DeductPoints( pSoldier, 0, 20000 );
}
// if we have a life damaging effect, deduct life points
if ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_LIFEDAMAGE ] == 0 && pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_LIFEDAMAGE ] > 0 )
{
if ( pSoldier->stats.bLife > OKLIFE )
{
INT8 lifepointdamage = pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_LIFEDAMAGE ];
INT8 lifepointdamage = pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_LIFEDAMAGE ];
INT8 applieddamage = pSoldier->stats.bLife;
INT8 applieddamage = pSoldier->stats.bLife;
pSoldier->stats.bLife = max(OKLIFE - 1, pSoldier->stats.bLife - lifepointdamage);
pSoldier->stats.bLife = max(OKLIFE - 8, pSoldier->stats.bLife - lifepointdamage);
applieddamage -= pSoldier->stats.bLife;
applieddamage -= pSoldier->stats.bLife;
pSoldier->iHealableInjury += (applieddamage * 100);
}
}
pSoldier->iHealableInjury += (applieddamage * 100);
}*/
}
// if we took an antidote, reduce poisoning
if ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_CUREPOISON ] > 0 )
// if we took an antidote, reduce poisoning
if ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_CUREPOISON ] > 0 )
{
if ( pSoldier->bPoisonSum > 0 )
{
if ( pSoldier->bPoisonSum > 0 )
if ( pSoldier->bPoisonBleeding > 0 )
{
if ( pSoldier->bPoisonBleeding > 0 )
{
pSoldier->bPoisonBleeding--;
}
else if ( pSoldier->bPoisonLife > 0 )
{
pSoldier->bPoisonLife--;
}
pSoldier->bPoisonSum--;
pSoldier->bPoisonBleeding--;
}
else if ( pSoldier->bPoisonLife > 0 )
{
pSoldier->bPoisonLife--;
}
pSoldier->bPoisonSum--;
}
}
+7
View File
@@ -2318,6 +2318,13 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
}
}
// Flugente: add an icon if we are currently in disguise
if ( MercPtrs[ pFace->ubSoldierID ]->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER) )
{
DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 22 );
bNumRightIcons++;
}
switch( pSoldier->bAssignment )
{
case DOCTOR:
+57
View File
@@ -101,6 +101,7 @@ static INT8 bTempFrequency;
void BombMessageBoxCallBack( UINT8 ubExitValue );
void TacticalFunctionSelectionMessageBoxCallBack( UINT8 ubExitValue ); // Flugente: callback after deciding what tactical function to use
void CorpseMessageBoxCallBack( UINT8 ubExitValue ); // Flugente: callback after deciding what to do with a corpse
void BoobyTrapMessageBoxCallBack( UINT8 ubExitValue );
void SwitchMessageBoxCallBack( UINT8 ubExitValue );
void BoobyTrapDialogueCallBack( void );
@@ -133,6 +134,8 @@ void StartBombMessageBox( SOLDIERTYPE * pSoldier, INT32 sGridNo );
void StartTacticalFunctionSelectionMessageBox( SOLDIERTYPE * pSoldier, INT32 sGridNo, INT8 bLevel ); // added by Flugente
void CleanWeapons();
void StartCorpseMessageBox( SOLDIERTYPE * pSoldier, INT32 sGridNo, INT8 bLevel ); // added by Flugente
BOOLEAN HandleCheckForBadChangeToGetThrough( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pTargetSoldier, INT32 sTargetGridNo , INT8 bLevel )
{
BOOLEAN fBadChangeToGetThrough = FALSE;
@@ -1647,6 +1650,11 @@ void HandleTacticalFunctionSelection( SOLDIERTYPE *pSoldier, INT32 sGridNo )
}
void HandleSoldierUseCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel )
{
StartCorpseMessageBox( pSoldier, sGridNo, bLevel );
}
void SoldierHandleDropItem( SOLDIERTYPE *pSoldier )
{
// LOOK IN PANDING DATA FOR ITEM TO DROP, AND LOCATION
@@ -2441,6 +2449,12 @@ OBJECTTYPE* InternalAddItemToPool( INT32 *psGridNo, OBJECTTYPE *pObject, INT8 bV
bRenderZHeightAboveLevel = 0;
}
// Flugente: if this item is a corpse, don't add it to the world. Instead spawn a corpse in its position
if ( HasItemFlag(pObject->usItem, CORPSE) && AddCorpseFromObject(pObject, *psGridNo, ubLevel ) )
{
return( NULL );
}
//CHRISL: We need to make sure that item stacks follow the OldInv stacking limits
// Copy the object we're working with the gTempObject so that we can use pObject later in this function
OBJECTTYPE poolObject = OBJECTTYPE(*pObject);
@@ -4418,6 +4432,19 @@ INT32 AdjustGridNoForItemPlacement( SOLDIERTYPE *pSoldier, INT32 sGridNo )
return( sActionGridNo );
}
// Flugente
void StartCorpseMessageBox( SOLDIERTYPE * pSoldier, INT32 sGridNo, INT8 bLevel )
{
gpTempSoldier = pSoldier;
// determine what is possible with this corpse
BOOLEAN fDecapitate = TRUE;
BOOLEAN fTakeClothes = TRUE;
BOOLEAN fTakeCorpse = TRUE;
if ( fDecapitate && fTakeClothes )
DoMessageBox( MSG_BOX_BASIC_SMALL_BUTTONS, TacticalStr[ CORPSE_SELECTION_STR ], GAME_SCREEN, MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS, CorpseMessageBoxCallBack, NULL );
}
void StartBombMessageBox( SOLDIERTYPE * pSoldier, INT32 sGridNo )
{
@@ -4667,6 +4694,36 @@ void TacticalFunctionSelectionMessageBoxCallBack( UINT8 ubExitValue )
}
}
// Flugente: callback after deciding what to do with a corpse
void CorpseMessageBoxCallBack( UINT8 ubExitValue )
{
if (gpTempSoldier)
{
INT32 nextGridNoinSight = gpTempSoldier->sGridNo;
nextGridNoinSight = NewGridNo( nextGridNoinSight, DirectionInc( gpTempSoldier->ubDirection ) );
INT8 level = gpTempSoldier->bTargetLevel;
switch (ubExitValue)
{
case 1:
DecapitateCorpse( gpTempSoldier, nextGridNoinSight, level );
break;
case 2:
GutCorpse( gpTempSoldier, nextGridNoinSight, level );
break;
case 3:
StripCorpse( gpTempSoldier, nextGridNoinSight, level );
break;
case 4:
TakeCorpse( gpTempSoldier, nextGridNoinSight, level );
break;
default:
break;
}
}
}
BOOLEAN HandItemWorks( SOLDIERTYPE *pSoldier, INT8 bSlot )
{
BOOLEAN fItemJustBroke = FALSE, fItemWorks = TRUE;
+2
View File
@@ -135,6 +135,8 @@ void HandleSoldierUseRemote( SOLDIERTYPE *pSoldier, INT32 sGridNo );
void HandleTacticalFunctionSelection( SOLDIERTYPE *pSoldier, INT32 sGridNo ); // Flugente: in tactical, open a selection box for different actions
void HandleSoldierUseCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel ); // Flugente: handle corpses
BOOLEAN ItemPoolOKForDisplay( ITEM_POOL *pItemPool, INT8 bZLevel );
INT16 GetNumOkForDisplayItemsInPool( ITEM_POOL *pItemPool, INT8 bZLevel );
+21 -4
View File
@@ -2523,7 +2523,16 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
SetRegionFastHelpText( &(gUDBFasthelpRegions[ iFirstDataRegion + cnt ]), pStr );
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + cnt ] );
cnt++;
}
}
//////////////////// COVERT ITEM
if ( HasItemFlag(gpItemDescObject->usItem, COVERT) )
{
swprintf( pStr, L"%s%s", szUDBGenSecondaryStatsTooltipText[ 31 ], szUDBGenSecondaryStatsExplanationsTooltipText[ 31 ]);
SetRegionFastHelpText( &(gUDBFasthelpRegions[ iFirstDataRegion + cnt ]), pStr );
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + cnt ] );
cnt++;
}
}
//////////////////////////////////////////////////////
@@ -5532,7 +5541,14 @@ void DrawSecondaryStats( OBJECTTYPE * gpItemDescObject )
{
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoSecondaryIcon, 11, gItemDescGenSecondaryRegions[cnt].sLeft+sOffsetX, gItemDescGenSecondaryRegions[cnt].sTop+sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
cnt++;
}
}
//////////////////// COVERT ITEM
if ( HasItemFlag(gpItemDescObject->usItem, COVERT) )
{
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoSecondaryIcon, 30, gItemDescGenSecondaryRegions[cnt].sLeft+sOffsetX, gItemDescGenSecondaryRegions[cnt].sTop+sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
cnt++;
}
}
void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
@@ -8938,8 +8954,9 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
// Print Values
for (UINT8 cnt2 = 0; cnt2 < 3; cnt2++)
{
if (UsingNewCTHSystem() == false && cnt2 > 0)
break;
// Flugente: no idea why we would want to skip this in OCTH, commenting this out
//if (UsingNewCTHSystem() == false && cnt2 > 0)
//break;
SetFontForeground( 5 );
sLeft = gItemDescAdvRegions[cnt-sFirstLine][cnt2+1].sLeft;
sWidth = gItemDescAdvRegions[cnt-sFirstLine][cnt2+1].sRight - sLeft;
+4 -4
View File
@@ -13148,11 +13148,11 @@ void BombInventoryMessageBoxCallBack( UINT8 ubExitValue )
if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( gpItemDescSoldier, DEMOLITIONS_NT ))
{
// increase trap level for Demolitions trait
gpItemDescSoldier->inv[ HANDPOS ][0]->data.bTrap = __min( max( 10, (8 + gSkillTraitValues.ubDEPlacedBombLevelBonus)), (( EffectiveExplosive( gpItemDescSoldier ) / 20) + (EffectiveExpLevel( gpItemDescSoldier ) / 3) + gSkillTraitValues.ubDEPlacedBombLevelBonus) );
(*gpItemDescObject)[0]->data.bTrap = __min( max( 10, (8 + gSkillTraitValues.ubDEPlacedBombLevelBonus)), (( EffectiveExplosive( gpItemDescSoldier ) / 20) + (EffectiveExpLevel( gpItemDescSoldier ) / 3) + gSkillTraitValues.ubDEPlacedBombLevelBonus) );
}
else
{
gpItemDescSoldier->inv[ HANDPOS ][0]->data.bTrap = __min( 10, ( EffectiveExplosive( gpItemDescSoldier ) / 20) + (EffectiveExpLevel( gpItemDescSoldier ) / 3) );
(*gpItemDescObject)[0]->data.bTrap = __min( 10, ( EffectiveExplosive( gpItemDescSoldier ) / 20) + (EffectiveExpLevel( gpItemDescSoldier ) / 3) );
}
// Flugente: We armed a bomb in our inventory. We will NOT add it to the item pool and the world bombs.
@@ -13164,8 +13164,8 @@ void BombInventoryMessageBoxCallBack( UINT8 ubExitValue )
// so we add 2 to all owner IDs passed through here and subtract 2 later
//if (gpItemDescSoldier->inv[HANDPOS].MoveThisObjectTo(gTempObject, 1) == 0)
{
gTempObject[0]->data.misc.ubBombOwner = gpItemDescSoldier->ubID + 2;
gTempObject[0]->data.ubDirection = gpItemDescSoldier->ubDirection; // Flugente: direction of bomb is direction of soldier
(*gpItemDescObject)[0]->data.misc.ubBombOwner = gpItemDescSoldier->ubID + 2;
(*gpItemDescObject)[0]->data.ubDirection = gpItemDescSoldier->ubDirection; // Flugente: direction of bomb is direction of soldier
//AddItemToPool( gsTempGridNo, &gTempObject, VISIBLE, gpItemDescSoldier->pathing.bLevel, WORLD_ITEM_ARMED_BOMB, 0 );
}
+15
View File
@@ -3357,6 +3357,21 @@ void SMInvClickCamoCallback( MOUSE_REGION * pRegion, INT32 iReason )
// Say OK acknowledge....
gpSMCurrentMerc->DoMercBattleSound( BATTLE_SOUND_COOL1 );
}
else if ( ApplySpyKit( gpSMCurrentMerc, gpItemPointer ) )
{
// Dirty
fInterfacePanelDirty = DIRTYLEVEL2;
// Check if it's the same now!
if ( gpItemPointer->exists() == false )
{
gbCompatibleApplyItem = FALSE;
EndItemPointer( );
}
// Say OK acknowledge....
gpSMCurrentMerc->DoMercBattleSound( BATTLE_SOUND_COOL1 );
}
else
{
// Send message
+53 -6
View File
@@ -734,13 +734,13 @@ extern OBJECTTYPE gTempObject;
#define CAMO_REMOVAL 0x00000400 //1024 // item can be used to remove camo
#define CLEANING_KIT 0x00000800 //2048 // weapon cleaning kit
/*#define ENEMY_NET_1_LVL_4 0x00001000 //4096
#define ENEMY_NET_2_LVL_4 0x00002000 //8192
#define ENEMY_NET_3_LVL_4 0x00004000 //16384
#define ENEMY_NET_4_LVL_4 0x00008000 //32768
#define CLOTHES_CIVILIAN 0x00001000 //4096 // with this item you can disguise as a civilian
#define GAROTTE 0x00002000 //8192 // this item is a garotte
#define COVERT 0x00004000 //16384 // if LBE, any gun inside will be covert. On a gun, it will covert in any LBE, even if the LBE does not have that tag itself
#define CORPSE 0x00008000 //32768 // a dead body
#define PLAYER_NET_1_LVL_1 0x00010000 //65536
#define PLAYER_NET_2_LVL_1 0x00020000 //131072
#define SKIN_BLOODCAT 0x00010000 //65536 // retrieve this by skinning (=decapitating) a bloodcat
/*#define PLAYER_NET_2_LVL_1 0x00020000 //131072
#define PLAYER_NET_3_LVL_1 0x00040000 //262144
#define PLAYER_NET_4_LVL_1 0x00080000 //524288
@@ -760,6 +760,49 @@ extern OBJECTTYPE gTempObject;
#define PLAYER_NET_4_LVL_4 0x80000000 //2147483648*/
// ----------------------------------------------------------------
// -------- added by Flugente: flags for objects --------
// the numbering of these flags is important. DO NOT CHANGE THEM, UNLESS YOU KNOW WHAT YOU ARE DOING!!!
#define CORPSE_M_SMALL 0x00000001 //1
#define CORPSE_M_BIG 0x00000002 //2
#define CORPSE_F 0x00000004 //4
#define CORPSE_NO_HEAD 0x00000008 //8
#define CORPSE_HAIR_BROWN 0x00000010 //16
#define CORPSE_HAIR_BLACK 0x00000020 //32
#define CORPSE_HAIR_WHITE 0x00000040 //64
#define CORPSE_HAIR_BLOND 0x00000080 //128
#define CORPSE_HAIR_RED 0x00000100 //256
#define CORPSE_SKIN_PINK 0x00000200 //512
#define CORPSE_SKIN_TAN 0x00000400 //1024
#define CORPSE_SKIN_DARK 0x00000800 //2048
#define CORPSE_SKIN_BLACK 0x00001000 //4096
#define CORPSE_VEST_BROWN 0x00002000 //8192
#define CORPSE_VEST_grey 0x00004000 //16384
#define CORPSE_VEST_GREEN 0x00008000 //32768
#define CORPSE_VEST_JEAN 0x00010000 //65536
#define CORPSE_VEST_RED 0x00020000 //131072
#define CORPSE_VEST_BLUE 0x00040000 //262144
#define CORPSE_VEST_YELLOW 0x00080000 //524288
#define CORPSE_VEST_WHITE 0x00100000 //1048576
#define CORPSE_VEST_BLACK 0x00200000 //2097152
#define CORPSE_VEST_GYELLOW 0x00400000 //4194304
#define CORPSE_VEST_PURPLE 0x00800000 //8388608
#define CORPSE_PANTS_GREEN 0x01000000 //16777216
#define CORPSE_PANTS_JEAN 0x02000000 //33554432
#define CORPSE_PANTS_TAN 0x04000000 //67108864
#define CORPSE_PANTS_BLACK 0x08000000 //134217728
#define CORPSE_PANTS_BLUE 0x10000000 //268435456
#define CORPSE_PANTS_BEIGE 0x20000000 //536870912
#define CORPSE_STRIPPED 0x40000000 //1073741824
//#define unused 0x80000000 //2147483648*/
// ----------------------------------------------------------------
// replaces candamage
//#define ITEM_DAMAGEABLE 0x0001
//// replaces canrepair
@@ -1703,6 +1746,10 @@ enum
IMP_TEACHING_EXP,
IMP_LOCKPICKING_EXP,
// Flugente: added covert ops
IMP_COVERT,
IMP_COVERT_EXP,
MAX_IMP_ITEM_TYPES
};
+17
View File
@@ -9144,6 +9144,23 @@ 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)) )
{
return( FALSE );
}
// we get the civilian disguise. AP costs will be checked and deducted here
if ( !pSoldier->DisguiseAsCivilian() )
return FALSE;
UseKitPoints( pObj, 100, pSoldier );
return( TRUE );
}
BOOLEAN ApplyCanteen( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAPs )
{
INT16 sPointsToUse;
+2
View File
@@ -196,6 +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
UINT32 ConvertProfileMoneyValueToObjectTypeMoneyValue( UINT8 ubStatus );
UINT8 ConvertObjectTypeMoneyValueToProfileMoneyValue( UINT32 uiMoneyAmount );
@@ -484,6 +485,7 @@ typedef struct
{
UINT8 usWaterType; // type of water source in this sector
UINT16 usNaturalDirt; // extra dirt percentage when firing in this sector
UINT8 usCurfewValue; // determines wether mercs disguising as civilian are automatically discovered (certain sectors are 'restricted' to civilians)
} SECTOR_EXT_DATA;
// get dirt increase for object with attachments, fConsiderAmmo: with ammo
+4 -4
View File
@@ -6104,11 +6104,11 @@ void EnterCombatMode( UINT8 ubStartingTeam )
if (!is_client || is_server) //hayden
{
StartPlayerTeamTurn( FALSE, TRUE );
StartPlayerTeamTurn( FALSE, TRUE );
if(is_client)send_EndTurn( ubStartingTeam ); //hayden
}
else
{
}
else
{
//ScreenMsg( FONT_YELLOW, MSG_CHAT, L"client skipped EnterCombatMode");
if(is_client)startCombat(ubStartingTeam);//clients other than server meet and send request for combat for server
}
+518 -31
View File
@@ -275,8 +275,8 @@ BOOLEAN gbCorpseValidForDecapitation[ NUM_CORPSES ] =
1,
1,
1,
1, // Bloodcat - changed to 1 to allow gutting
1, // Cow - changed to 1 to allow gutting
1, // Bloodcat - changed to 1 to allow skinning (works like decapitating)
0,
0,
0,
0,
@@ -495,6 +495,9 @@ INT32 AddRottingCorpse( ROTTING_CORPSE_DEFINITION *pCorpseDef )
// Copy elements in
memcpy( pCorpse, pCorpseDef, sizeof( ROTTING_CORPSE_DEFINITION ) );
if ( pCorpseDef->fHeadTaken )
pCorpse->def.usFlags |= ROTTING_CORPSE_HEAD_TAKEN;
uiDirectionUseFlag = ANITILE_USE_DIRECTION_FOR_START_FRAME;
// If we are a soecial type...
@@ -818,7 +821,7 @@ BOOLEAN TurnSoldierIntoCorpse( SOLDIERTYPE *pSoldier, BOOLEAN fRemoveMerc, BOOLE
// Setup some values!
memset( &Corpse, 0, sizeof( Corpse ) );
Corpse.ubBodyType = pSoldier->ubBodyType;
Corpse.sGridNo = pSoldier->sGridNo;
Corpse.sGridNo = pSoldier->sGridNo;
Corpse.dXPos = pSoldier->dXPos;
Corpse.dYPos = pSoldier->dYPos;
Corpse.bLevel = pSoldier->pathing.bLevel;
@@ -895,6 +898,18 @@ BOOLEAN TurnSoldierIntoCorpse( SOLDIERTYPE *pSoldier, BOOLEAN fRemoveMerc, BOOLE
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;
// Determine corpse type!
ubType = (UINT8)gubAnimSurfaceCorpseID[ pSoldier->ubBodyType][ pSoldier->usAnimState ];
@@ -1763,7 +1778,7 @@ INT32 FindNearestAvailableGridNoForCorpse( ROTTING_CORPSE_DEFINITION *pDef, INT8
BOOLEAN IsValidDecapitationCorpse( ROTTING_CORPSE *pCorpse )
{
if ( (pCorpse->def.usFlags & ROTTING_CORPSE_GUTTED) )
if ( (pCorpse->def.usFlags & ROTTING_CORPSE_HEAD_TAKEN) )
{
return( FALSE );
}
@@ -1797,14 +1812,12 @@ ROTTING_CORPSE *GetCorpseAtGridNo( INT32 sGridNo, INT8 bLevel )
}
void DecapitateCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel )
void DecapitateCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel )
{
ROTTING_CORPSE *pCorpse;
ROTTING_CORPSE_DEFINITION CorpseDef;
UINT16 usHeadIndex = HEAD_1;
static UINT16 usBloodCatMeatIndex = 1566;
static UINT16 usCowMeatIndex = 1565;
static UINT16 usBloodCatSkinIndex = 232;
pCorpse = GetCorpseAtGridNo( sGridNo, bLevel );
@@ -1812,41 +1825,30 @@ void DecapitateCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel )
{
return;
}
if ( IsValidDecapitationCorpse( pCorpse ) )
{
// Decapitate.....
// Copy corpse definition...
memcpy( &CorpseDef, &(pCorpse->def), sizeof( ROTTING_CORPSE_DEFINITION ) );
// Flugente: if the corpse is of a cow or a bloodcat, we don't take its head, we simply gut it and give meat instead of a head
if ( CorpseDef.ubType == BLOODCAT_DEAD || CorpseDef.ubType == COW_DEAD )
{
pCorpse->def.usFlags |= (ROTTING_CORPSE_HEAD_TAKEN|ROTTING_CORPSE_GUTTED);
if ( CorpseDef.ubType == BLOODCAT_DEAD )
{
if ( HasItemFlag(usBloodCatMeatIndex, MEAT_BLOODCAT) || GetFirstItemWithFlag(&usBloodCatMeatIndex, MEAT_BLOODCAT) )
usHeadIndex = usBloodCatMeatIndex;
}
else
{
if ( HasItemFlag(usCowMeatIndex, COW_MEAT) || GetFirstItemWithFlag(&usCowMeatIndex, COW_MEAT) )
usHeadIndex = usCowMeatIndex;
}
}
// Add new one...
CorpseDef.ubType = gDecapitatedCorpse[ CorpseDef.ubType ];
pCorpse->def.usFlags |= (ROTTING_CORPSE_HEAD_TAKEN|ROTTING_CORPSE_GUTTED);
pCorpse->def.usFlags |= ROTTING_CORPSE_HEAD_TAKEN;
CorpseDef.fHeadTaken = TRUE;
if ( CorpseDef.ubType != 0 )
{
// Remove old one...
RemoveCorpse( pCorpse->iID );
AddRottingCorpse( &CorpseDef );
INT32 iCorpseID = AddRottingCorpse( &CorpseDef );
if ( iCorpseID != -1 )
{
gRottingCorpse[ iCorpseID ].def.usFlags |= ROTTING_CORPSE_HEAD_TAKEN;
}
}
// Add head item.....
@@ -1880,6 +1882,12 @@ void DecapitateCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel )
}
if ( pCorpse->def.ubType == BLOODCAT_DEAD )
{
if ( HasItemFlag(usBloodCatSkinIndex, SKIN_BLOODCAT) || GetFirstItemWithFlag(&usBloodCatSkinIndex, SKIN_BLOODCAT) )
usHeadIndex = usBloodCatSkinIndex;
}
if ( usHeadIndex > 0 )
{
CreateItem( usHeadIndex, 100, &gTempObject );
@@ -1889,7 +1897,404 @@ void DecapitateCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel )
NotifySoldiersToLookforItems( );
}
}
}
// Flugente: can this corpse be gutted?
BOOLEAN IsValidGutCorpse( ROTTING_CORPSE *pCorpse )
{
if ( pCorpse->def.ubType == ROTTING_STAGE2 || (pCorpse->def.usFlags & ROTTING_CORPSE_GUTTED) )
return( FALSE );
return( pCorpse->def.ubType == BLOODCAT_DEAD || pCorpse->def.ubType == COW_DEAD );
}
// Flugente: gut a corpse
void GutCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel )
{
ROTTING_CORPSE *pCorpse = GetCorpseAtGridNo( sGridNo, bLevel );
if ( pCorpse == NULL )
return;
// can this thing be gutted?
if ( IsValidGutCorpse( pCorpse ) )
{
// numbers for the meat acquired by gutting. These values respond to the standard GameDir values, if they have other values in the ini, no problem, we'll search for them
static UINT16 usBloodCatMeatIndex = 1566;
static UINT16 usCowMeatIndex = 1565;
UINT16 meatindex = 0;
pCorpse->def.usFlags |= ROTTING_CORPSE_GUTTED;
if ( pCorpse->def.ubType == BLOODCAT_DEAD )
{
if ( HasItemFlag(usBloodCatMeatIndex, MEAT_BLOODCAT) || GetFirstItemWithFlag(&usBloodCatMeatIndex, MEAT_BLOODCAT) )
meatindex = usBloodCatMeatIndex;
}
else
{
if ( HasItemFlag(usCowMeatIndex, COW_MEAT) || GetFirstItemWithFlag(&usCowMeatIndex, COW_MEAT) )
meatindex = usCowMeatIndex;
}
if ( meatindex > 0 )
{
CreateItem( meatindex, 100, &gTempObject );
AddItemToPool( sGridNo, &gTempObject, INVISIBLE, 0, 0, 0 );
// All teams lok for this...
NotifySoldiersToLookforItems( );
}
}
else
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Not possible, you sick, sick individual!" );
}
// Flugente: can clothes be taken off of this corpse?
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) );
}
// Flugente: take the clothes off a corpse and wear them
void StripCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel )
{
ROTTING_CORPSE *pCorpse = GetCorpseAtGridNo( sGridNo, bLevel );
if ( pCorpse == NULL )
return;
// 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 ) )
{
// we took the clothes, mark this
pCorpse->def.usFlags |= ROTTING_CORPSE_CLOTHES_TAKEN;
}
}
else
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"No clothes to take!" );
}
// Flugente: can clothes be taken off of this corpse?
BOOLEAN IsValidTakeCorpse( ROTTING_CORPSE *pCorpse )
{
if ( pCorpse->def.ubType >= BLOODCAT_DEAD || pCorpse->def.ubType == NO_CORPSE )
return( FALSE );
return( TRUE );
}
// Flugente: take a corpse into your hand, thereby removing it from the field
void TakeCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel )
{
ROTTING_CORPSE *pCorpse = GetCorpseAtGridNo( sGridNo, bLevel );
if ( pCorpse == NULL )
return;
// can this corpse be picked up?
if ( IsValidTakeCorpse( pCorpse ) )
{
// is there a 'corpse' item?
UINT16 corpseitem = 0;
if ( GetFirstItemWithFlag(&corpseitem, CORPSE) )
{
// we have to make sure this can be placed in our hands, as corpses can only be carried in hands.
// At this point, we will have a knife in our first hand, so check if our second hand is free
if ( !(pSoldier->inv[SECONDHANDPOS].exists()) )
{
CreateItem( corpseitem, 100, &gTempObject );
if(CanItemFitInPosition(pSoldier, &gTempObject, SECONDHANDPOS, FALSE))
{
// determine Body type
if ( pCorpse->def.ubBodyType == BIGMALE || pCorpse->def.ubBodyType == STOCKYMALE || pCorpse->def.ubBodyType == FATCIV )
gTempObject[0]->data.sObjectFlag |= CORPSE_M_BIG;
else if ( pCorpse->def.ubBodyType == REGFEMALE || pCorpse->def.ubBodyType == MINICIV || pCorpse->def.ubBodyType == DRESSCIV )
gTempObject[0]->data.sObjectFlag |= CORPSE_F;
if ( pCorpse->def.usFlags & ROTTING_CORPSE_HEAD_TAKEN )
gTempObject[0]->data.sObjectFlag |= CORPSE_NO_HEAD;
if ( pCorpse->def.usFlags & ROTTING_CORPSE_CLOTHES_TAKEN )
gTempObject[0]->data.sObjectFlag |= CORPSE_STRIPPED;
// now we have to get the correct flags for the object from the corpse, so that upon recreating the corpse, it looks the same
UINT8 headpal = 0, skinpal = 0, vestpal = 0, pantspal = 0;
GetPaletteRepIndexFromID(pCorpse->def.HeadPal, &headpal);
GetPaletteRepIndexFromID(pCorpse->def.SkinPal, &skinpal);
GetPaletteRepIndexFromID(pCorpse->def.VestPal, &vestpal);
GetPaletteRepIndexFromID(pCorpse->def.PantsPal, &pantspal);
switch ( headpal )
{
case 0:
gTempObject[0]->data.sObjectFlag |= CORPSE_HAIR_BLOND;
break;
case 1:
gTempObject[0]->data.sObjectFlag |= CORPSE_HAIR_BROWN;
break;
case 2:
gTempObject[0]->data.sObjectFlag |= CORPSE_HAIR_BLACK;
break;
case 3:
gTempObject[0]->data.sObjectFlag |= CORPSE_HAIR_WHITE;
break;
case 4:
default:
gTempObject[0]->data.sObjectFlag |= CORPSE_HAIR_RED;
break;
}
switch ( skinpal )
{
case 13:
gTempObject[0]->data.sObjectFlag |= CORPSE_SKIN_PINK;
break;
case 14:
gTempObject[0]->data.sObjectFlag |= CORPSE_SKIN_TAN;
break;
case 15:
gTempObject[0]->data.sObjectFlag |= CORPSE_SKIN_DARK;
break;
case 16:
default:
gTempObject[0]->data.sObjectFlag |= CORPSE_SKIN_BLACK;
break;
}
switch ( vestpal )
{
case 17:
gTempObject[0]->data.sObjectFlag |= CORPSE_VEST_BROWN;
break;
case 18:
gTempObject[0]->data.sObjectFlag |= CORPSE_VEST_grey;
break;
case 19:
gTempObject[0]->data.sObjectFlag |= CORPSE_VEST_GREEN;
break;
case 20:
gTempObject[0]->data.sObjectFlag |= CORPSE_VEST_JEAN;
break;
case 21:
gTempObject[0]->data.sObjectFlag |= CORPSE_VEST_RED;
break;
case 22:
gTempObject[0]->data.sObjectFlag |= CORPSE_VEST_BLUE;
break;
case 23:
gTempObject[0]->data.sObjectFlag |= CORPSE_VEST_YELLOW;
break;
case 24:
gTempObject[0]->data.sObjectFlag |= CORPSE_VEST_WHITE;
break;
case 25:
gTempObject[0]->data.sObjectFlag |= CORPSE_VEST_BLACK;
break;
case 26:
gTempObject[0]->data.sObjectFlag |= CORPSE_VEST_GYELLOW;
break;
case 27:
default:
gTempObject[0]->data.sObjectFlag |= CORPSE_VEST_PURPLE;
break;
}
switch ( pantspal )
{
case 7:
gTempObject[0]->data.sObjectFlag |= CORPSE_PANTS_GREEN;
break;
case 8:
gTempObject[0]->data.sObjectFlag |= CORPSE_PANTS_JEAN;
break;
case 9:
gTempObject[0]->data.sObjectFlag |= CORPSE_PANTS_TAN;
break;
case 10:
gTempObject[0]->data.sObjectFlag |= CORPSE_PANTS_BLACK;
break;
case 11:
gTempObject[0]->data.sObjectFlag |= CORPSE_PANTS_BLUE;
break;
case 12:
default:
gTempObject[0]->data.sObjectFlag |= CORPSE_PANTS_BEIGE;
break;
}
gTempObject.MoveThisObjectTo(pSoldier->inv[SECONDHANDPOS], ALL_OBJECTS, pSoldier, SECONDHANDPOS);
if ( pCorpse->def.ubType != 0 )
{
// Remove corpse...
RemoveCorpse( pCorpse->iID );
}
}
}
else
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"No free hand to carry corpse!" );
}
}
}
// Flugente: create a corpse from an object and plce it in the world
BOOLEAN AddCorpseFromObject(OBJECTTYPE* pObj, INT32 sGridNo, INT8 bLevel )
{
if ( !pObj || !HasItemFlag(pObj->usItem, CORPSE) )
return FALSE;
ROTTING_CORPSE_DEFINITION Corpse;
if ( (*pObj)[0]->data.sObjectFlag & CORPSE_M_BIG )
{
if ( (*pObj)[0]->data.sObjectFlag & CORPSE_NO_HEAD )
Corpse.ubType = MMERC_JFK;
else
Corpse.ubType = MMERC_BCK;
Corpse.ubBodyType = BIGMALE;
}
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_F )
{
if ( (*pObj)[0]->data.sObjectFlag & CORPSE_NO_HEAD )
Corpse.ubType = FMERC_JFK;
else
Corpse.ubType = FMERC_BCK;
Corpse.ubBodyType = REGFEMALE;
}
else
{
if ( (*pObj)[0]->data.sObjectFlag & CORPSE_M_SMALL )
Corpse.ubType = SMERC_JFK;
else
Corpse.ubType = SMERC_BCK;
Corpse.ubBodyType = REGMALE;
}
Corpse.sGridNo = sGridNo;
Corpse.dXPos = CenterX(Corpse.sGridNo);
Corpse.dYPos = CenterY(Corpse.sGridNo);
Corpse.sHeightAdjustment = 0;
// check the objects flagmask and set the corpse palette IDs accordingly
// Hair
if ( (*pObj)[0]->data.sObjectFlag & CORPSE_HAIR_BROWN )
SET_PALETTEREP_ID( Corpse.HeadPal, "BROWNHEAD" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_HAIR_BLACK )
SET_PALETTEREP_ID( Corpse.HeadPal, "BLACKHEAD" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_HAIR_WHITE )
SET_PALETTEREP_ID( Corpse.HeadPal, "WHITEHEAD" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_HAIR_BLOND )
SET_PALETTEREP_ID( Corpse.HeadPal, "BLONDHEAD" );
else
SET_PALETTEREP_ID( Corpse.HeadPal, "REDHEAD" );
// Skin
if ( (*pObj)[0]->data.sObjectFlag & CORPSE_SKIN_PINK )
SET_PALETTEREP_ID( Corpse.SkinPal, "PINKSKIN" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_SKIN_TAN )
SET_PALETTEREP_ID( Corpse.SkinPal, "TANSKIN" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_SKIN_DARK )
SET_PALETTEREP_ID( Corpse.SkinPal, "DARKSKIN" );
else
SET_PALETTEREP_ID( Corpse.SkinPal, "BLACKSKIN" );
// Vest
if ( (*pObj)[0]->data.sObjectFlag & CORPSE_VEST_BROWN )
SET_PALETTEREP_ID( Corpse.VestPal, "BROWNVEST" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_VEST_grey )
SET_PALETTEREP_ID( Corpse.VestPal, "greyVEST" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_VEST_GREEN )
SET_PALETTEREP_ID( Corpse.VestPal, "GREENVEST" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_VEST_JEAN )
SET_PALETTEREP_ID( Corpse.VestPal, "JEANVEST" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_VEST_RED )
SET_PALETTEREP_ID( Corpse.VestPal, "REDVEST" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_VEST_BLUE )
SET_PALETTEREP_ID( Corpse.VestPal, "BLUEVEST" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_VEST_YELLOW )
SET_PALETTEREP_ID( Corpse.VestPal, "YELLOWVEST" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_VEST_WHITE )
SET_PALETTEREP_ID( Corpse.VestPal, "WHITEVEST" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_VEST_BLACK )
SET_PALETTEREP_ID( Corpse.VestPal, "BLACKSHIRT" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_VEST_GYELLOW )
SET_PALETTEREP_ID( Corpse.VestPal, "GYELLOWSHIRT" );
else
SET_PALETTEREP_ID( Corpse.VestPal, "PURPLESHIRT" );
// Pants
if ( (*pObj)[0]->data.sObjectFlag & CORPSE_PANTS_GREEN )
SET_PALETTEREP_ID( Corpse.PantsPal, "GREENPANTS" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_PANTS_JEAN )
SET_PALETTEREP_ID( Corpse.PantsPal, "JEANPANTS" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_PANTS_TAN )
SET_PALETTEREP_ID( Corpse.PantsPal, "TANPANTS" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_PANTS_BLACK )
SET_PALETTEREP_ID( Corpse.PantsPal, "BLACKPANTS" );
else if ( (*pObj)[0]->data.sObjectFlag & CORPSE_PANTS_BLUE )
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();
Corpse.usFlags = 0; // no flags here, at least not the new ones
Corpse.bLevel = bLevel;
Corpse.bVisible = 1;
Corpse.bNumServicingCrows = 0;
Corpse.ubProfile = NO_PROFILE;
Corpse.fHeadTaken = FALSE;
Corpse.ubAIWarningValue = 20;
INT32 iCorpseID = AddRottingCorpse( &Corpse );
if ( iCorpseID != -1 )
{
AllMercsOnTeamLookForCorpse(&( gRottingCorpse[ iCorpseID ] ), OUR_TEAM);
if ( (*pObj)[0]->data.sObjectFlag & CORPSE_NO_HEAD )
gRottingCorpse[ iCorpseID ].def.usFlags |= ROTTING_CORPSE_HEAD_TAKEN;
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;
return TRUE;
}
return FALSE;
}
@@ -2552,3 +2957,85 @@ UINT8 GetNearestRottingCorpseAIWarning( INT32 sGridNo )
return( canbezombie );
}
#endif
// 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 )
{
if ( !pCorpse )
return FALSE;
switch ( pCorpse->def.ubType )
{
case SMERC_JFK:
case SMERC_BCK:
case SMERC_FWD:
case SMERC_DHD:
case SMERC_PRN:
case SMERC_WTR:
case SMERC_FALL:
case SMERC_FALLF:
case M_DEAD1:
case M_DEAD2:
case H_DEAD1:
case H_DEAD2:
case S_DEAD1:
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:
case MMERC_DHD:
case MMERC_PRN:
case MMERC_WTR:
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 FMERC_JFK:
case FMERC_BCK:
case FMERC_FWD:
case FMERC_DHD:
case FMERC_PRN:
case FMERC_WTR:
case FMERC_FALL:
case FMERC_FALLF:
case W_DEAD1:
case W_DEAD2:
if ( pSoldier )
{
if ( pSoldier->ubBodyType == REGFEMALE )
return TRUE;
}
else
return TRUE;
break;
default:
break;
}
return FALSE;
}
+18 -1
View File
@@ -91,8 +91,12 @@ enum RottingCorpseDefines
// Flugente: corpses can now be gutted after they have been decapitated. Atm there is no corpse that can be both gutted and decapitated (to be done later)
#define ROTTING_CORPSE_HEAD_TAKEN 0x00001000 // head has been taken off
#define ROTTING_CORPSE_GUTTED 0x00001000 // corpse has been gutted
#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;
@@ -199,6 +203,16 @@ ROTTING_CORPSE *GetCorpseAtGridNo( INT32 sGridNo , INT8 bLevel );
BOOLEAN IsValidDecapitationCorpse( ROTTING_CORPSE *pCorpse );
void DecapitateCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel );
// Flugente: actions for the covert opts trait
BOOLEAN IsValidGutCorpse( ROTTING_CORPSE *pCorpse );
void GutCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel );
BOOLEAN IsValidStripCorpse( ROTTING_CORPSE *pCorpse );
void StripCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel );
BOOLEAN IsValidTakeCorpse( ROTTING_CORPSE *pCorpse );
void TakeCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel );
BOOLEAN AddCorpseFromObject(OBJECTTYPE* pObj, INT32 sGridNo, INT8 bLevel );
void GetBloodFromCorpse( SOLDIERTYPE *pSoldier );
UINT16 GetCorpseStructIndex( ROTTING_CORPSE_DEFINITION *pCorpseDef, BOOLEAN fForImage );
@@ -221,4 +235,7 @@ UINT8 GetNearestRottingCorpseAIWarning( INT32 sGridNo );
BOOLEAN CorpseOkToSpawnZombie( ROTTING_CORPSE * pCorpse, UINT16* pAnimState );
#endif
// Flugente: can we take the clothes of this corpse?
BOOLEAN CorpseOkToDress( ROTTING_CORPSE * pCorpse, SOLDIERTYPE* pSoldier );
#endif
+4 -1
View File
@@ -2926,7 +2926,10 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
case 752:
// Code: decapitate
DecapitateCorpse( pSoldier, pSoldier->sTargetGridNo, pSoldier->bTargetLevel );
//DecapitateCorpse( pSoldier, pSoldier->sTargetGridNo, pSoldier->bTargetLevel );
// Flugente: instead of jsut decapitating, we call a selection window where we can choose what to do with the corpse
HandleSoldierUseCorpse( pSoldier, pSoldier->sTargetGridNo, pSoldier->bTargetLevel ); // Flugente: handle corpses
break;
case 753:
+754 -6
View File
@@ -6315,6 +6315,10 @@ void SoldierGotHitGunFire( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sD
}
}
// Flugente: if hit in legs or torso, blood will be on our uniform - this unifrom can't be used to disguise someone anymore
if ( ubHitLocation == AIM_SHOT_TORSO || ubHitLocation == AIM_SHOT_LEGS )
pSoldier->bSoldierFlagMask |= SOLDIER_DAMAGED_UNIFORM;
// IF HERE AND GUY IS DEAD, RETURN!
if ( pSoldier->flags.uiStatusFlags & SOLDIER_DEAD )
{
@@ -6361,6 +6365,10 @@ void SoldierGotHitGunFire( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sD
void SoldierGotHitExplosion( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sDamage, UINT16 bDirection, UINT16 sRange, UINT8 ubAttackerID, UINT8 ubSpecial, UINT8 ubHitLocation )
{
// Flugente: if hit in legs or torso, blood will be on our uniform - this unifrom can't be used to disguise someone anymore
if ( ubHitLocation == AIM_SHOT_TORSO || ubHitLocation == AIM_SHOT_LEGS )
pSoldier->bSoldierFlagMask |= SOLDIER_DAMAGED_UNIFORM;
INT32 sNewGridNo;
// IF HERE AND GUY IS DEAD, RETURN!
@@ -6529,6 +6537,9 @@ void SoldierGotHitExplosion( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16
void SoldierGotHitBlade( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sDamage, UINT16 bDirection, UINT16 sRange, UINT8 ubAttackerID, UINT8 ubSpecial, UINT8 ubHitLocation )
{
// Flugente: if hit in legs or torso, blood will be on our uniform - this unifrom can't be used to disguise someone anymore
if ( ubHitLocation == AIM_SHOT_TORSO || ubHitLocation == AIM_SHOT_LEGS )
pSoldier->bSoldierFlagMask |= SOLDIER_DAMAGED_UNIFORM;
// IF HERE AND GUY IS DEAD, RETURN!
if ( pSoldier->flags.uiStatusFlags & SOLDIER_DEAD )
@@ -11684,7 +11695,8 @@ void SOLDIERTYPE::EVENT_SoldierBeginBladeAttack( INT32 sGridNo, UINT8 ubDirectio
}
else
{
if ( IsValidDecapitationCorpse( pCorpse ) )
// Flugente: decapitation action now also performs gutting, stripping and taking corpses
if ( IsValidDecapitationCorpse( pCorpse ) || IsValidGutCorpse( pCorpse ) || IsValidStripCorpse( pCorpse ) || IsValidTakeCorpse( pCorpse ) )
{
this->EVENT_InitNewSoldierAnim( DECAPITATE, 0 , FALSE );
}
@@ -14393,6 +14405,742 @@ void SOLDIERTYPE::CleanWeapon()
}
}
extern INT16 uiNIVSlotType[NUM_INV_SLOTS];
// do we look like a civilian?
BOOLEAN SOLDIERTYPE::LooksLikeACivilian( void )
{
// if we have any camo: not covert
if ( GetWornCamo(this) > 0 || GetWornUrbanCamo(this) > 0 || GetWornDesertCamo(this) > 0 || GetWornSnowCamo(this) > 0 )
return FALSE;
if ( UsingNewInventorySystem() )
{
INT8 invsize = (INT8)this->inv.size();
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop) // ... for all items in our inventory ...
{
if ( this->inv[bLoop].exists() )
{
// if we have a back pack: not covert
if ( bLoop == BPACKPOCKPOS )
return FALSE;
// do not check the LBE itself (we already checked for camo above)
if ( bLoop >= VESTPOCKPOS && bLoop <= CPACKPOCKPOS )
continue;
BOOLEAN checkfurther = FALSE;
// further checks it item is not covert. This means that a gun that has that tag will not be detectedif if its inside a pocket!
if ( bLoop == HANDPOS || bLoop == SECONDHANDPOS || bLoop == GUNSLINGPOCKPOS || bLoop == HELMETPOS || bLoop == VESTPOS || bLoop == LEGPOS || bLoop == HEAD1POS || bLoop == HEAD2POS )
checkfurther = TRUE;
else if ( bLoop == KNIFEPOCKPOS && !HasItemFlag(this->inv[bLoop].usItem, COVERT) )
checkfurther = TRUE;
else if ( !HasItemFlag(this->inv[bLoop].usItem, COVERT) )
{
checkfurther = TRUE;
// item will be detected if someone looks - check for the LBE item that gave us this slot. If that one is covert, this item is also covert
UINT8 checkslot = 0;
switch (uiNIVSlotType[bLoop])
{
case 3:
checkslot = VESTPOCKPOS;
break;
case 4:
if ( bLoop == 23 || bLoop == 35 || bLoop == 36 || bLoop == 37 || bLoop == 38 )
checkslot = LTHIGHPOCKPOS;
else
checkslot = RTHIGHPOCKPOS;
break;
case 5:
checkslot = CPACKPOCKPOS;
break;
default:
return FALSE;
break;
}
// found a slot to check for LBE
if ( checkslot > 0 )
{
// if LBE is covert
if ( this->inv[checkslot].exists() && HasItemFlag(this->inv[checkslot].usItem, COVERT) )
// pass for this item
checkfurther = FALSE;
}
}
if ( checkfurther )
{
// if that item is a gun, explosives, military armour or facewear, we're screwed
if ( (Item[this->inv[bLoop].usItem].usItemClass & (IC_WEAPON|IC_GRENADE|IC_BOMB) ) ||
( (Item[this->inv[bLoop].usItem].usItemClass & (IC_ARMOUR) ) && !Item[this->inv[bLoop].usItem].leatherjacket && Armour[ Item[this->inv[bLoop].usItem].ubClassIndex ].ubProtection > 10 ) ||
( Item[this->inv[bLoop].usItem].nightvisionrangebonus > 0 || Item[this->inv[bLoop].usItem].hearingrangebonus > 0 )
)
return FALSE;
}
}
}
}
else // old inventory system. No LBE here, nothing fancy
{
INT8 invsize = (INT8)this->inv.size();
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop) // ... for all items in our inventory ...
{
if ( this->inv[bLoop].exists() )
{
if ( !HasItemFlag(this->inv[bLoop].usItem, COVERT) )
{
// if that item is a gun, explosives, military armour or facewear, we're screwed
if ( (Item[this->inv[bLoop].usItem].usItemClass & (IC_WEAPON|IC_GRENADE|IC_BOMB) ) ||
( (Item[this->inv[bLoop].usItem].usItemClass & (IC_ARMOUR) ) && !Item[this->inv[bLoop].usItem].leatherjacket && Armour[ Item[this->inv[bLoop].usItem].ubClassIndex ].ubProtection > 10 ) ||
( Item[this->inv[bLoop].usItem].nightvisionrangebonus > 0 || Item[this->inv[bLoop].usItem].hearingrangebonus > 0 )
)
return FALSE;
}
}
}
}
return TRUE;
}
// do we look like a soldier?
BOOLEAN SOLDIERTYPE::LooksLikeASoldier( void )
{
return TRUE;
}
// is our equipment too good for a soldier?
BOOLEAN SOLDIERTYPE::EquipmentTooGood( BOOLEAN fCloselook )
{
// check the guns in our hands an rifle sling
// alert if we have more than 2, any of them has too much attachments or they are way too cool
UINT8 numberofguns = 0;
UINT8 ubCurrentProgress = CurrentPlayerProgressPercentage();
UINT8 maxcoolnessallowed = 1 + ubCurrentProgress / 10;
maxcoolnessallowed += 2; // TODO adjust for level and uniform
UINT16 maxitemsize = 4;
if ( UsingNewInventorySystem() )
{
INT8 invsize = (INT8)this->inv.size();
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop) // ... for all items in our inventory ...
{
if ( this->inv[bLoop].exists() )
{
// if we have a back pack: not covert
if ( bLoop == BPACKPOCKPOS )
return FALSE;
// further checks it item is not covert. This means that a gun that has that tag will not be detectedif if its inside a pocket!
if ( bLoop == HANDPOS || bLoop == SECONDHANDPOS || bLoop == GUNSLINGPOCKPOS || bLoop == HELMETPOS || bLoop == VESTPOS || bLoop == LEGPOS || bLoop == HEAD1POS || bLoop == HEAD2POS ||
!HasItemFlag(this->inv[bLoop].usItem, COVERT) )
{
// item will be detected if someone looks - check for the LBE item that gave us this slot. If that one is covert, this item is also covert
UINT8 checkslot = 0;
switch (uiNIVSlotType[bLoop])
{
case 3:
checkslot = VESTPOCKPOS;
break;
case 4:
if ( bLoop == 23 || bLoop == 35 || bLoop == 36 || bLoop == 37 || bLoop == 38 )
checkslot = LTHIGHPOCKPOS;
else
checkslot = RTHIGHPOCKPOS;
break;
case 5:
checkslot = CPACKPOCKPOS;
break;
default:
return FALSE;
break;
}
// found a slot to check for LBE
if ( checkslot > 0 )
{
// if LBE is covert
if ( this->inv[checkslot].exists() && HasItemFlag(this->inv[checkslot].usItem, COVERT) )
// pass for this item
continue;
}
// if that item is a gun, explosives, military armour or facewear, investigate further
if ( (Item[this->inv[bLoop].usItem].usItemClass & (IC_GUN|IC_LAUNCHER|IC_ARMOUR|IC_FACE) ) )
{
if ( (Item[this->inv[bLoop].usItem].usItemClass & (IC_GUN|IC_LAUNCHER) ) )
{
++numberofguns;
if ( numberofguns > 2 )
return TRUE;
OBJECTTYPE * pObj = &(this->inv[bLoop]); // ... get pointer for this item ...
if ( pObj != NULL )
{
for(INT16 i = 0; i < pObj->ubNumberOfObjects; ++i) // ... there might be multiple items here (item stack), so for each one ...
{
// loop over every item and its attachments
if ( Item[pObj->usItem].ubCoolness > maxcoolnessallowed )
return TRUE;
UINT8 numberofattachments = 0;
// for every objects, we also have to check wether there are weapon attachments (eg. underbarrel grenade launchers), and cool them down too
attachmentList::iterator iterend = (*pObj)[i]->attachments.end();
for (attachmentList::iterator iter = (*pObj)[i]->attachments.begin(); iter != iterend; ++iter)
{
if ( iter->exists() )
{
// loop over every item and its attachments
if ( Item[iter->usItem].ubCoolness > maxcoolnessallowed )
return TRUE;
++numberofattachments;
}
}
// no ordinary soldier is allowed that many attachemnts > not covert
if ( numberofattachments > gGameExternalOptions.iMaxEnemyAttachments )
return TRUE;
}
}
}
}
}
}
}
}
else // old inventory system. No LBE here, nothing fancy
{
INT8 invsize = (INT8)this->inv.size();
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop) // ... for all items in our inventory ...
{
if ( this->inv[bLoop].exists() )
{
// if that item is a gun, explosives, military armour or facewear, investigate further
if ( !HasItemFlag(this->inv[bLoop].usItem, COVERT) && (Item[this->inv[bLoop].usItem].usItemClass & (IC_GUN|IC_LAUNCHER|IC_ARMOUR|IC_FACE) ) )
{
if ( (Item[this->inv[bLoop].usItem].usItemClass & (IC_GUN|IC_LAUNCHER) ) )
{
++numberofguns;
if ( numberofguns > 2 )
return TRUE;
OBJECTTYPE * pObj = &(this->inv[bLoop]); // ... get pointer for this item ...
if ( pObj != NULL )
{
for(INT16 i = 0; i < pObj->ubNumberOfObjects; ++i) // ... there might be multiple items here (item stack), so for each one ...
{
// loop over every item and its attachments
if ( Item[pObj->usItem].ubCoolness > maxcoolnessallowed )
return TRUE;
UINT8 numberofattachments = 0;
// for every objects, we also have to check wether there are weapon attachments (eg. underbarrel grenade launchers), and cool them down too
attachmentList::iterator iterend = (*pObj)[i]->attachments.end();
for (attachmentList::iterator iter = (*pObj)[i]->attachments.begin(); iter != iterend; ++iter)
{
if ( iter->exists() )
{
// loop over every item and its attachments
if ( Item[iter->usItem].ubCoolness > maxcoolnessallowed )
return TRUE;
++numberofattachments;
}
}
// no ordinary soldier is allowed that many attachments > not covert
if ( numberofattachments > gGameExternalOptions.iMaxEnemyAttachments )
return TRUE;
}
}
}
}
}
}
}
return FALSE;
}
// are we in covert mode? we need to have the correct flag set, and not wear anything suspicious, or behave in a suspicious way
BOOLEAN SOLDIERTYPE::SeemsLegit( UINT8 ubObserverID )
{
SOLDIERTYPE* pSoldier = MercPtrs[ubObserverID];
if ( !pSoldier )
return TRUE;
// if we don't have the Flag: not covert
// important: no messages up to this point. the function will get called a lot, up to this point there is nothing unusual
if ( !(this->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER) ) )
return FALSE;
// if we are in a suspicious stance: not covert
if ( this->usAnimState == NINJA_SPINKICK ||
this->usAnimState == NINJA_PUNCH ||
this->usAnimState == NINJA_LOWKICK ||
this->usAnimState == PUNCH_LOW ||
this->usAnimState == DECAPITATE ||
this->usAnimState == CROWBAR_ATTACK ||
this->usAnimState == THROW_GRENADE_STANCE ||
this->usAnimState == THROW_KNIFE_SP_BM ||
this->usAnimState == DODGE_ONE ||
this->usAnimState == SLICE ||
this->usAnimState == STAB ||
this->usAnimState == CROUCH_STAB ||
this->usAnimState == PUNCH ||
this->usAnimState == PUNCH_BREATH ||
this->usAnimState == KICK_DOOR ||
this->usAnimState == CUTTING_FENCE ||
this->usAnimState == THROW_KNIFE ||
this->usAnimState == PLANT_BOMB ||
this->usAnimState == USE_REMOTE ||
this->usAnimState == TAKE_BLOOD_FROM_CORPSE ||
this->usAnimState == PICK_LOCK ||
this->usAnimState == LOCKPICK_CROUCHED ||
this->usAnimState == STEAL_ITEM_CROUCHED ||
this->usAnimState == JUMPWINDOWS
)
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s was seen performing suspicious activities!", this->name );
return FALSE;
}
BOOLEAN looklikeaciv = this->LooksLikeACivilian();
// if we are trying to dress like a civilian, but aren't sucessful: not covert
if ( this->bSoldierFlagMask & SOLDIER_COVERT_CIV && !looklikeaciv)
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s does not look like a civilian!", this->name );
return FALSE;
}
BOOLEAN looklikeasoldier = this->LooksLikeASoldier();
// if we are trying to dress like a soldier, but aren't sucessful: not covert
if ( this->bSoldierFlagMask & SOLDIER_COVERT_SOLDIER && !looklikeasoldier)
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s does not look like a soldier!", this->name );
return FALSE;
}
UINT8 covertlevel = NUM_SKILL_TRAITS( this, COVERT_NT ); // our level in covert operations
INT32 distance = GetRangeFromGridNoDiff(this->sGridNo, pSoldier->sGridNo);
// if we are closer than this, our cover will always break if we do not have the skill
// if we have the skill, our cover will blow if we dress up as a soldier, but not if we are dressed like a civilian
INT32 discoverrange = gSkillTraitValues.sCOCloseDetectionRange;
if ( distance < discoverrange )
{
switch ( covertlevel )
{
case 2:
// a covert ops expert can get as close as he wants, even dressed up as a soldier, without arousing suspicion
// exceptions: we are discovered if we are close and bleeding, or if we are drunk while dressed as a soldier
{
// if we are openly bleeding: not covert
if ( this->bBleeding > 0 )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s bleeding was discovered!", this->name );
return FALSE;
}
if ( this->bSoldierFlagMask & SOLDIER_COVERT_SOLDIER && GetDrunkLevel( this ) != SOBER )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s is drunk and doesn't look like a soldier!", this->name );
return FALSE;
}
}
break;
case 1:
// at lvl covert ops, we can be discovered if we are too close to the enemy and bleed or dressed up as a soldier
// however, if we are dressed up as a civilian, we can get as close as we like, we won't be discovered
{
// if we are openly bleeding: not covert
if ( this->bBleeding > 0 )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s bleeding was discovered!", this->name );
return FALSE;
}
if ( this->bSoldierFlagMask & SOLDIER_COVERT_SOLDIER )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"On closer inspection, %s's disguise does not hold!", this->name );
return FALSE;
}
}
break;
case 0:
default:
// without the covert ops skill, we can only dress up as civilians. We will be discovered if we get too close to the enemy
if ( (this->bSoldierFlagMask & SOLDIER_COVERT_NPC_SPECIAL) == 0 )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"On closer inspection, %s's disguise does not hold!", this->name );
return FALSE;
}
break;
}
}
if ( this->bSoldierFlagMask & SOLDIER_COVERT_CIV )
{
// civilians are suspicious if they are found in certain sectors. Especially at night
// sector specific value:
// 0 - civilians are always ok
// 1 - civilians are suspicious at night
// 2 - civilians are always suspicious
UINT8 sectordata = 0;
UINT8 ubSectorId = SECTOR(gWorldSectorX, gWorldSectorY);
if ( gbWorldSectorZ > 0 )
// underground we are always suspicious
sectordata = 2;
else if ( ubSectorId >= 0 && ubSectorId < 256 )
sectordata = SectorExternalData[ubSectorId][gbWorldSectorZ].usCurfewValue;
if ( sectordata > 1 )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s isn't supposed to be here!", this->name );
return FALSE;
}
// is it night?
else if ( sectordata == 1 && GetTimeOfDayAmbientLightLevel() < NORMAL_LIGHTLEVEL_DAY + 2 )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s isn't supposed to be here at this time!", this->name );
return FALSE;
}
// check wether we are around a fresh corpse - this will make us much more suspicious
INT32 cnt;
ROTTING_CORPSE * pCorpse;
for ( cnt = 0; cnt < giNumRottingCorpse; ++cnt )
{
pCorpse = &(gRottingCorpse[ cnt ] );
if ( pCorpse && pCorpse->fActivated && pCorpse->def.ubAIWarningValue > 0 && PythSpacesAway( this->sGridNo, pCorpse->def.sGridNo ) <= 5 )
{
// a corpse was found near our position. If the soldier observing us can see it, he will be alarmed
if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pCorpse->def.sGridNo, pCorpse->def.bLevel, 3, TRUE, CALC_FROM_WANTED_DIR ) )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s was seen near a fresh corpse!", this->name );
return FALSE;
}
}
}
}
if ( this->bSoldierFlagMask & SOLDIER_COVERT_SOLDIER )
{
// if our equipment is too good, that is suspicious... not covert!
if ( this->EquipmentTooGood( (distance < discoverrange) ) )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s equipment raises a few eyebrows!", this->name );
return FALSE;
}
// are we targeting a buddy of our observer?
if ( this->ubTargetID && MercPtrs[this->ubTargetID] && MercPtrs[this->ubTargetID]->bTeam == pSoldier->bTeam )
{
// if we aiming at a soldier, others will notice our intent... not covert!
if ( WeaponReady(this) )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s is seen targeting a soldier!", this->name );
return FALSE;
}
}
// even as a soldier, we will be caught around fresh corpses
if (distance < gSkillTraitValues.sCOCloseDetectionRangeSoldierCorpse)
{
// check wether we are around a fresh corpse - this will make us much more suspicious
// I deem this necessary, to avoid cheap exploits by nefarious players :-)
INT32 cnt;
ROTTING_CORPSE * pCorpse;
for ( cnt = 0; cnt < giNumRottingCorpse; ++cnt )
{
pCorpse = &(gRottingCorpse[ cnt ] );
if ( pCorpse && pCorpse->fActivated && pCorpse->def.ubAIWarningValue > 0 && PythSpacesAway( this->sGridNo, pCorpse->def.sGridNo ) <= 5 )
{
// a corpse was found near our position. If the soldier observing us can see it, he will be alarmed
if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pCorpse->def.sGridNo, pCorpse->def.bLevel, 3, TRUE, CALC_FROM_WANTED_DIR ) )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s was seen near a fresh corpse!", this->name );
return FALSE;
}
}
}
}
}
return TRUE;
}
// do we recognize someone else as a combatant?
BOOLEAN SOLDIERTYPE::RecognizeAsCombatant(UINT8 ubTargetID)
{
// this will only work with the new trait system
if (!gGameOptions.fNewTraitSystem)
return TRUE;
SOLDIERTYPE* pSoldier = MercPtrs[ubTargetID];
if ( !pSoldier )
return TRUE;
// if neither of the 2 persons is covert, always return true
if ( ( (pSoldier->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER)) == 0 ) && ( (this->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER)) == 0 ) )
return TRUE;
// only members of the player team can ever be covert, sorry AI
if ( pSoldier->bTeam != OUR_TEAM )
return TRUE;
// neutral characters just dont care
if ( this->aiData.bNeutral )
return TRUE;
// check for for vehicles and creatures... weird things happen
if ( IsVehicle(pSoldier) || pSoldier->bTeam == CREATURE_TEAM || this->bTeam == CREATURE_TEAM )
return TRUE;
// checking someone from our team...
if ( this->bTeam == pSoldier->bTeam )
{
// not in covert mode: we recognize him
if ( (pSoldier->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER)) == 0 )
return TRUE;
else
// we don't because we accept that he is covert (to not blow his cover)
return FALSE;
}
// hack: if this is attacking us at this very moment by punching, do not recognize him...
// this resolves the problem that we attack someone from behind and kill him instantly, but the game mechanic forces him to turn before
// only allow this if we are not yet alerted (we are suprised, so we don't recognize him in the moment of the attack
// also: only allow if he's next to us
if ( this->aiData.bAlertStatus < STATUS_RED && pSoldier->ubTargetID == this->ubID )
{
INT32 nextGridNoinSight = NewGridNo( pSoldier->sGridNo, DirectionInc( pSoldier->ubDirection ) );
if ( nextGridNoinSight == this->sGridNo && this->pathing.bLevel == pSoldier->pathing.bLevel )
{
if ( pSoldier->usAnimState == PUNCH )
return FALSE;
else if ( pSoldier->usAnimState == PUNCH_BREATH )
return TRUE;
}
}
// do we recognize this guy as an enemy?
if ( !pSoldier->SeemsLegit(this->ubID) )
{
// aha, he/she's a spy! Blow cover
if ( pSoldier->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER) )
{
pSoldier->LooseDisguise();
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s has seen through %s disguise!", this->name, pSoldier->name );
// we have uncovered a spy! Get alerted, if we aren't already
if ( this->aiData.bAlertStatus < STATUS_BLACK )
this->aiData.bAlertStatus = STATUS_BLACK;
}
return TRUE;
}
return FALSE;
}
// dress up in our natural state
void SOLDIERTYPE::LooseDisguise( void )
{
// show our true colours
UINT16 usPaletteAnimSurface = LoadSoldierAnimationSurface( this, this->usAnimState );
if ( usPaletteAnimSurface != INVALID_ANIMATION_SURFACE )
{
UINT8 ubProfileIndex;
MERCPROFILESTRUCT * pProfile;
ubProfileIndex = this->ubProfile;
pProfile = &(gMercProfiles[ubProfileIndex]);
SET_PALETTEREP_ID ( this->VestPal, pProfile->VEST );
SET_PALETTEREP_ID ( this->PantsPal, pProfile->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();
}
// 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 );
}
}
// 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)
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 ) )
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();
}
// 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)
return FALSE;
// action is only possible if we have the covert ops trait
UINT8 skilllevel = NUM_SKILL_TRAITS( this, COVERT_NT );
if ( skilllevel < 1)
return FALSE;
INT16 apcost = (APBPConstants[AP_DISGUISE] * ( gSkillTraitValues.sCODisguiseAPReduction * skilllevel))/100;
if ( !EnoughPoints( this, apcost, 0, TRUE ) )
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
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 );
}
}
DeductPoints( this, apcost, 0 );
return TRUE;
}
INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
{
INT8 bBandaged; //,savedOurTurn;
@@ -16455,13 +17203,13 @@ BOOLEAN HAS_SKILL_TRAIT( SOLDIERTYPE * pSoldier, UINT8 uiSkillTraitNumber )
{
for ( INT8 bCnt = 0; bCnt < min(30,bMaxTraits); bCnt++ )
{
if ( uiSkillTraitNumber > 0 && uiSkillTraitNumber <= NUM_MAJOR_TRAITS )
if ( uiSkillTraitNumber > 0 && (uiSkillTraitNumber <= NUM_MAJOR_TRAITS || uiSkillTraitNumber == COVERT_NT) )
{
if (pSoldier->stats.ubSkillTraits[ bCnt ] == uiSkillTraitNumber)
{
return( TRUE );
}
else if ( pSoldier->stats.ubSkillTraits[ bCnt ] > 0 && pSoldier->stats.ubSkillTraits[ bCnt ] <= NUM_MAJOR_TRAITS )
else if ( pSoldier->stats.ubSkillTraits[ bCnt ] > 0 && (pSoldier->stats.ubSkillTraits[ bCnt ] <= NUM_MAJOR_TRAITS || pSoldier->stats.ubSkillTraits[ bCnt ] == COVERT_NT) )
{
bNumMajorTraitsCounted++;
}
@@ -16511,14 +17259,14 @@ INT8 NUM_SKILL_TRAITS( SOLDIERTYPE * pSoldier, UINT8 uiSkillTraitNumber )
{
for ( INT8 bCnt = 0; bCnt < min(30,bMaxTraits); bCnt++ )
{
if ( uiSkillTraitNumber > 0 && uiSkillTraitNumber <= NUM_MAJOR_TRAITS )
if ( uiSkillTraitNumber > 0 && (uiSkillTraitNumber <= NUM_MAJOR_TRAITS || uiSkillTraitNumber == COVERT_NT) )
{
if ( pSoldier->stats.ubSkillTraits[ bCnt ] == uiSkillTraitNumber )
{
bNumberOfTraits++;
bNumMajorTraitsCounted++;
}
else if ( pSoldier->stats.ubSkillTraits[ bCnt ] > 0 && pSoldier->stats.ubSkillTraits[ bCnt ] <= NUM_MAJOR_TRAITS )
else if ( pSoldier->stats.ubSkillTraits[ bCnt ] > 0 && (pSoldier->stats.ubSkillTraits[ bCnt ] <= NUM_MAJOR_TRAITS || pSoldier->stats.ubSkillTraits[ bCnt ] == COVERT_NT ) )
{
bNumMajorTraitsCounted++;
}
@@ -16537,7 +17285,7 @@ INT8 NUM_SKILL_TRAITS( SOLDIERTYPE * pSoldier, UINT8 uiSkillTraitNumber )
}
}
// cannot have more than one same minor trait
if( uiSkillTraitNumber > NUM_MAJOR_TRAITS )
if( uiSkillTraitNumber > NUM_MAJOR_TRAITS && uiSkillTraitNumber != COVERT_NT)
return ( min(1, bNumberOfTraits) );
else
return ( min(2, bNumberOfTraits) );
+33 -5
View File
@@ -345,12 +345,12 @@ enum
// easier than adding 32 differently named variables. DO NOT CHANGE THEM, UNLESS YOU KNOW WHAT YOU ARE DOING!!!
#define SOLDIER_DRUGGED 0x00000001 //1 // Soldier is on drugs
#define SOLDIER_NO_AP 0x00000002 //2 // Soldier has no APs this turn (fix for reinforcement bug)
/*#define WH40K_BOLTER 0x00000004 //4
#define WH40K_FLAMER 0x00000008 //8
#define SOLDIER_COVERT_CIV 0x00000004 //4 // Soldier is currently disguised as a civilian
#define SOLDIER_COVERT_SOLDIER 0x00000008 //8 // Soldier is currently disguised as an enemy soldier
#define WH40K_POWER_ARMOR 0x00000010 //16
#define WH40K_POWER_PACK 0x00000020 //32
#define WH40K_JUMPPACK 0x00000040 //64
#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 WH40K_ROSARIUS 0x00000100 //256
@@ -1456,6 +1456,34 @@ public:
// use any cleaning kits to clean weapons in inventory
void CleanWeapon();
// Flugente: functions for the covert ops trait
// are we in covert mode? we need to have the correct flag set, and not wear anything suspicious, or behave in a suspicious way
// do we look like a civilian?
BOOLEAN LooksLikeACivilian( void );
// do we look like a soldier?
BOOLEAN LooksLikeASoldier( void );
// is our equipment too good for a soldier?
BOOLEAN EquipmentTooGood( BOOLEAN fCloselook );
// does soldier ubObserverID recognize us as his enemy?
BOOLEAN SeemsLegit( UINT8 ubObserverID );
// do we recognize someone else as a combatant?
BOOLEAN RecognizeAsCombatant(UINT8 ubTargetID);
// loose disguise, dress up in our natural state
void LooseDisguise( void );
// dress up like a civilian
BOOLEAN DisguiseAsCivilian( void );
// dress up like an enemy soldier
BOOLEAN DisguiseAsSoldierFromCorpse( UINT32 usFlag );
//////////////////////////////////////////////////////////////////////////////
}; // SOLDIERTYPE;
+13 -3
View File
@@ -1701,6 +1701,16 @@ BOOLEAN RecruitRPC( UINT8 ubCharNum )
GiveQuestRewardPoint( pSoldier->sSectorX, pSoldier->sSectorY, 6, MIGUEL );
}
// Flugente: people recruited in Arulco are known to the enemy as civilians or even soldiers. So they will be covert whn recruiting them. Of course, this is not for the rebels...
if ( ubCharNum == DEVIN || ubCharNum == HAMOUS || ubCharNum == SLAY || ubCharNum == VINCE || ubCharNum == MADDOG || ubCharNum == MICKY )
{
pNewSoldier->bSoldierFlagMask |= (SOLDIER_COVERT_CIV|SOLDIER_COVERT_NPC_SPECIAL);
}
else if ( ubCharNum == IGGY || ubCharNum == CONRAD )
{
pNewSoldier->bSoldierFlagMask |= (SOLDIER_COVERT_SOLDIER|SOLDIER_COVERT_NPC_SPECIAL);
}
// handle town loyalty adjustment
HandleTownLoyaltyForNPCRecruitment( pNewSoldier );
@@ -2650,14 +2660,14 @@ INT8 ProfileHasSkillTrait( INT32 ubProfileID, INT8 bSkillTrait )
{
for ( INT8 bCnt = 0; bCnt < gSkillTraitValues.ubMaxNumberOfTraits; bCnt++ )
{
if ( bSkillTrait > 0 && bSkillTrait <= NUM_MAJOR_TRAITS )
if ( bSkillTrait > 0 && (bSkillTrait <= DOCTOR_NT || bSkillTrait == COVERT_NT ) )
{
if ( gMercProfiles[ubProfileID].bSkillTraits[ bCnt ] == bSkillTrait )
{
bNumTraits++;
bNumMajorTraitsCounted++;
}
else if ( gMercProfiles[ubProfileID].bSkillTraits[ bCnt ] > 0 && gMercProfiles[ubProfileID].bSkillTraits[ bCnt ] <= NUM_MAJOR_TRAITS )
else if ( gMercProfiles[ubProfileID].bSkillTraits[ bCnt ] > 0 && (gMercProfiles[ubProfileID].bSkillTraits[ bCnt ] <= DOCTOR_NT || gMercProfiles[ubProfileID].bSkillTraits[ bCnt ] <= COVERT_NT) )
{
bNumMajorTraitsCounted++;
}
@@ -2676,7 +2686,7 @@ INT8 ProfileHasSkillTrait( INT32 ubProfileID, INT8 bSkillTrait )
}
}
// cannot have more than 1 rade of minor traits or 2 grades of a major traits
if( bSkillTrait > NUM_MAJOR_TRAITS )
if( bSkillTrait > DOCTOR_NT && bSkillTrait != COVERT_NT )
return ( min(1, bNumTraits) );
else
return ( min(2, bNumTraits) );
+3 -3
View File
@@ -238,7 +238,7 @@ void SoldierTooltip( SOLDIERTYPE* pSoldier )
CHAR16 pStrAux[50];
swprintf( pStrAux, L"(%s)", gzMercSkillTextNew[pSoldier->stats.ubSkillTraits[0]]);
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_1], pStrInfo, pStrAux );
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_2], pStrInfo, gzMercSkillTextNew[pSoldier->stats.ubSkillTraits[1] + 19] );
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_2], pStrInfo, gzMercSkillTextNew[pSoldier->stats.ubSkillTraits[1] + NEWTRAIT_MERCSKILL_EXPERTOFFSET] );
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_3], pStrInfo, gzMercSkillTextNew[pSoldier->stats.ubSkillTraits[2]] );
//swprintf( pStrInfo, L"%s\n", pStrInfo );
}
@@ -247,7 +247,7 @@ void SoldierTooltip( SOLDIERTYPE* pSoldier )
CHAR16 pStrAux[50];
swprintf( pStrAux, L"(%s)", gzMercSkillTextNew[pSoldier->stats.ubSkillTraits[1]]);
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_1], pStrInfo, pStrAux );
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_2], pStrInfo, gzMercSkillTextNew[pSoldier->stats.ubSkillTraits[2] + 19] );
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_2], pStrInfo, gzMercSkillTextNew[pSoldier->stats.ubSkillTraits[2] + NEWTRAIT_MERCSKILL_EXPERTOFFSET] );
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_3], pStrInfo, gzMercSkillTextNew[pSoldier->stats.ubSkillTraits[0]] );
}
else if (( pSoldier->stats.ubSkillTraits[0] == pSoldier->stats.ubSkillTraits[2] ) && pSoldier->stats.ubSkillTraits[0] != 0 )
@@ -255,7 +255,7 @@ void SoldierTooltip( SOLDIERTYPE* pSoldier )
CHAR16 pStrAux[50];
swprintf( pStrAux, L"(%s)", gzMercSkillTextNew[pSoldier->stats.ubSkillTraits[0]]);
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_1], pStrInfo, pStrAux );
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_2], pStrInfo, gzMercSkillTextNew[pSoldier->stats.ubSkillTraits[2] + 19] );
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_2], pStrInfo, gzMercSkillTextNew[pSoldier->stats.ubSkillTraits[2] + NEWTRAIT_MERCSKILL_EXPERTOFFSET] );
swprintf( pStrInfo, gzTooltipStrings[STR_TT_SKILL_TRAIT_3], pStrInfo, gzMercSkillTextNew[pSoldier->stats.ubSkillTraits[1]] );
}
else
+1 -1
View File
@@ -4449,7 +4449,7 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
/*// Flugente: spawn items while debugging
if ( gusSelectedSoldier != NOBODY )
{
static UINT16 usitem = 1576;
static UINT16 usitem = 142;
static INT16 status = 100;
static FLOAT temperature = 0.0;
+65 -5
View File
@@ -8960,8 +8960,21 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget,
if ( iImpact > 0 && !TANK( pTarget ) )
{
// Flugente: ammo can now add the lifedamage drug effect. This will kill the target in a few turns.
// this is intended to work on darts, but it is possible on any ammo
if ( AmmoTypes[ubAmmoType].ammoflag & AMMO_NEUROTOXIN )
{
pTarget->bSoldierFlagMask |= SOLDIER_DRUGGED;
if ( AmmoTypes[ubAmmoType].dart && sHitBy > 20 )
// Add lifedamage effects
pTarget->drugs.bFutureDrugEffect[ DRUG_TYPE_LIFEDAMAGE ] = min(pTarget->drugs.bFutureDrugEffect[ DRUG_TYPE_LIFEDAMAGE ] + 3, 127);
pTarget->drugs.bDrugEffectRate[DRUG_TYPE_LIFEDAMAGE] = 1;
pTarget->drugs.bDrugEffect[DRUG_TYPE_LIFEDAMAGE] = 0;
pTarget->drugs.bDrugSideEffectRate[DRUG_TYPE_LIFEDAMAGE] = 0;
pTarget->drugs.bDrugSideEffect[DRUG_TYPE_LIFEDAMAGE] = 127;
pTarget->drugs.bTimesDrugUsedSinceSleep[ DRUG_TYPE_LIFEDAMAGE ]++;
}
else if ( AmmoTypes[ubAmmoType].dart && sHitBy > 20 )
{
if (pubSpecial)
{
@@ -9434,13 +9447,13 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO
INT32 iImpact, iFluke, iBonus;
// Flugente: check for underbarrel weapons and use that object if necessary (think of bayonets)
OBJECTTYPE* pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[HANDPOS]) );
if (fBladeAttack)
{
iImpact = ( EffectiveExpLevel( pSoldier ) / 2); // 0 to 4 for level
// Flugente: check for underbarrel weapons and use that object if necessary (think of bayonets)
OBJECTTYPE* pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[HANDPOS]) );
iImpact += GetDamage(pObj);
iImpact += EffectiveStrength( pSoldier, FALSE ) / 20; // 0 to 5 for strength, adjusted by damage taken
@@ -9677,6 +9690,34 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO
iBonus += 10; // +10%
}
// Flugente: if we are using a garotte, there is a chance that we score an instakill
// our level in covert ops and wether the target is aware of us has a huge impact
if ( pObj && HasItemFlag(pObj->usItem, GAROTTE) )
{
INT32 instakillchance = 0;
INT32 resistchance = 20;
if ( !SoldierTo3DLocationLineOfSightTest( pSoldier, pTarget->sGridNo, pTarget->pathing.bLevel, 3, TRUE, CALC_FROM_WANTED_DIR ) )
instakillchance += 30;
UINT8 skilllevel = NUM_SKILL_TRAITS( pSoldier, COVERT_NT );
instakillchance += skilllevel * gSkillTraitValues.sCoMeleeInstakillBonus;
if ( pTarget->aiData.bAlertStatus == STATUS_YELLOW )
resistchance += 20;
else if ( pTarget->aiData.bAlertStatus >= STATUS_RED )
resistchance += 50;
if ( pTarget->bCollapsed )
resistchance = 0;
// killchance gets lowered if garotte is in bad shape
instakillchance *= ( (*pObj)[0]->data.objectStatus / 100 );
if ( Random(instakillchance) >= Random(resistchance) )
iImpact += 500;
}
// apply all bonuses
iImpact = (iImpact * (100 + iBonus) + 50) / 100; // round it properly
@@ -9925,6 +9966,25 @@ UINT32 CalcChanceHTH( SOLDIERTYPE * pAttacker,SOLDIERTYPE *pDefender, INT16 ubAi
{
iAttRating += gSkillTraitValues.bCtHModifierHtHAttack; // Make HtH attacks a little more problematic for untrained mercs
// Flugente: if we are using a garotte, alter the attack rating on wether we are used in to this weapon, and wether our target can see us
if ( HasItemFlag(usInHand, GAROTTE) )
{
// using a garotte is pretty hard, we get a malus as default value
INT32 garottemodifier = -30;
UINT8 skilllevel = NUM_SKILL_TRAITS( pAttacker, COVERT_NT );
garottemodifier += skilllevel * gSkillTraitValues.sCOMeleeCTHBonus;
if ( pDefender->bCollapsed )
garottemodifier += 80;
// if this guy can see us, get a big malus!
else if ( SoldierTo3DLocationLineOfSightTest( pAttacker, pDefender->sGridNo, pDefender->pathing.bLevel, 3, TRUE, CALC_FROM_WANTED_DIR ) )
garottemodifier -= 80;
iAttRating += garottemodifier;
}
// bare hands - bonus for Martial arts
if (!pAttacker->usAttackingWeapon && HAS_SKILL_TRAIT( pAttacker, MARTIAL_ARTS_NT ))
{
+47 -1
View File
@@ -172,6 +172,49 @@ enum
AMMO_FLAME,
};
// -------- added by Flugente: various ammo flags --------
// flags used for various ammo properties (easier than adding 32 differently named variables). DO NOT CHANGE THEM, UNLESS YOU KNOW WHAT YOU ARE DOING!!!
#define AMMO_NEUROTOXIN 0x00000001 //1 // this ammo adds the cyanide drug effect to its target, killing it in a few turns
/*#define FULL_SANDBAG 0x00000002 //2
#define SHOVEL 0x00000004 //4
#define CONCERTINA 0x00000008 //8
#define WATER_DRUM 0x00000010 //16 // water drums allow to refill canteens in the sector they are in
#define MEAT_BLOODCAT 0x00000020 //32 // retrieve this by gutting a bloodcat
#define COW_MEAT 0x00000040 //64 // retrieve this by gutting a cow
#define BELT_FED 0x00000080 //128 // item can be fed externally
#define AMMO_BELT 0x00000100 //256 // this item can be used to feed externally
#define AMMO_BELT_VEST 0x00000200 //512 // this is a vest that can contain AMMO_BELT items in its medium slots
#define COVERT_OPS_KIT 0x00000400 //1024 // this kit can restore the covert ops disguise
#define RAG 0x00000800 //2048 // this item is a rag and can be used to remove camo
#define ENEMY_NET_1_LVL_4 0x00001000 //4096
#define ENEMY_NET_2_LVL_4 0x00002000 //8192
#define ENEMY_NET_3_LVL_4 0x00004000 //16384
#define ENEMY_NET_4_LVL_4 0x00008000 //32768
#define PLAYER_NET_1_LVL_1 0x00010000 //65536
#define PLAYER_NET_2_LVL_1 0x00020000 //131072
#define PLAYER_NET_3_LVL_1 0x00040000 //262144
#define PLAYER_NET_4_LVL_1 0x00080000 //524288
#define PLAYER_NET_1_LVL_2 0x00100000 //1048576
#define PLAYER_NET_2_LVL_2 0x00200000 //2097152
#define PLAYER_NET_3_LVL_2 0x00400000 //4194304
#define PLAYER_NET_4_LVL_2 0x00800000 //8388608
#define PLAYER_NET_1_LVL_3 0x01000000 //16777216
#define PLAYER_NET_2_LVL_3 0x02000000 //33554432
#define PLAYER_NET_3_LVL_3 0x04000000 //67108864
#define PLAYER_NET_4_LVL_3 0x08000000 //134217728
#define PLAYER_NET_1_LVL_4 0x10000000 //268435456
#define PLAYER_NET_2_LVL_4 0x20000000 //536870912
#define PLAYER_NET_3_LVL_4 0x40000000 //1073741824
#define PLAYER_NET_4_LVL_4 0x80000000 //2147483648*/
// ----------------------------------------------------------------
typedef struct
{
UINT32 uiIndex;
@@ -216,10 +259,13 @@ typedef struct
BOOLEAN tracerEffect;
FLOAT temperatureModificator; // Flugente: modificator for weapon temperature
INT16 poisonPercentage; // Flugente: modificator for weapon temperature
FLOAT dirtModificator; // Flugente: modificator for weapon temperature
FLOAT dirtModificator; // Flugente: modificator for dirt generation
//zilpin: pellet spread patterns externalized in XML
INT32 spreadPattern;
// Flugente: item flag for various properties. Way easier than 32 boolean flags
UINT32 ammoflag;
} AMMOTYPE;
+39 -33
View File
@@ -81,7 +81,8 @@ ammotypeStartElementHandle(void *userData, const XML_Char *name, const XML_Char
strcmp(name, "monsterSpit") == 0 ||
strcmp(name, "temperatureModificator") == 0 ||
strcmp(name, "PoisonPercentage") == 0 ||
strcmp(name, "dirtModificator") == 0 ))
strcmp(name, "dirtModificator") == 0 ||
strcmp(name, "ammoflag") == 0 ))
{
pData->curElement = ELEMENT_PROPERTY;
@@ -298,6 +299,11 @@ ammotypeEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = ELEMENT;
pData->curAmmoType.dirtModificator = (FLOAT) atof(pData->szCharData);
}
else if(strcmp(name, "ammoflag") == 0)
{
pData->curElement = ELEMENT;
pData->curAmmoType.ammoflag = (UINT32) atol(pData->szCharData);
}
pData->maxReadDepth--;
}
@@ -390,39 +396,39 @@ BOOLEAN WriteAmmoTypeStats()
FilePrintf(hFile,"\t<AMMOTYPE>\r\n");
FilePrintf(hFile,"\t\t<uiIndex>%d</uiIndex>\r\n", cnt );
FilePrintf(hFile,"\t\t<fontColour>%d</fontColour>\r\n", AmmoTypes[cnt].fontColour );
FilePrintf(hFile,"\t\t<grayed>%d</grayed>\r\n", AmmoTypes[cnt].grayed );
FilePrintf(hFile,"\t\t<offNormal>%d</offNormal>\r\n", AmmoTypes[cnt].offNormal );
FilePrintf(hFile,"\t\t<onNormal>%d</onNormal>\r\n", AmmoTypes[cnt].onNormal );
FilePrintf(hFile,"\t\t<structureImpactReductionMultiplier>%d</structureImpactReductionMultiplier>\r\n", AmmoTypes[cnt].structureImpactReductionMultiplier );
FilePrintf(hFile,"\t\t<structureImpactReductionDivisor>%d</structureImpactReductionDivisor>\r\n", AmmoTypes[cnt].structureImpactReductionDivisor );
FilePrintf(hFile,"\t\t<armourImpactReductionMultiplier>%d</armourImpactReductionMultiplier>\r\n", AmmoTypes[cnt].armourImpactReductionMultiplier );
FilePrintf(hFile,"\t\t<armourImpactReductionDivisor>%d</armourImpactReductionDivisor>\r\n", AmmoTypes[cnt].armourImpactReductionDivisor );
FilePrintf(hFile,"\t\t<beforeArmourDamageMultiplier>%d</beforeArmourDamageMultiplier>\r\n", AmmoTypes[cnt].beforeArmourDamageMultiplier );
FilePrintf(hFile,"\t\t<beforeArmourDamageDivisor>%d</beforeArmourDamageDivisor>\r\n", AmmoTypes[cnt].beforeArmourDamageDivisor );
FilePrintf(hFile,"\t\t<afterArmourDamageMultiplier>%d</afterArmourDamageMultiplier>\r\n", AmmoTypes[cnt].afterArmourDamageMultiplier );
FilePrintf(hFile,"\t\t<afterArmourDamageDivisor>%d</afterArmourDamageDivisor>\r\n", AmmoTypes[cnt].afterArmourDamageDivisor );
FilePrintf(hFile,"\t\t<zeroMinimumDamage>%d</zeroMinimumDamage>\r\n", AmmoTypes[cnt].zeroMinimumDamage );
FilePrintf(hFile,"\t\t<canGoThrough>%d</canGoThrough>\r\n", AmmoTypes[cnt].canGoThrough );
FilePrintf(hFile,"\t\t<standardIssue>%d</standardIssue>\r\n", AmmoTypes[cnt].standardIssue );
FilePrintf(hFile,"\t\t<numberOfBullets>%d</numberOfBullets>\r\n", AmmoTypes[cnt].numberOfBullets );
FilePrintf(hFile,"\t\t<multipleBulletDamageMultiplier>%d</multipleBulletDamageMultiplier>\r\n", AmmoTypes[cnt].multipleBulletDamageMultiplier );
FilePrintf(hFile,"\t\t<multipleBulletDamageDivisor>%d</multipleBulletDamageDivisor>\r\n", AmmoTypes[cnt].multipleBulletDamageDivisor );
FilePrintf(hFile,"\t\t<highExplosive>%d</highExplosive>\r\n", AmmoTypes[cnt].highExplosive );
FilePrintf(hFile,"\t\t<explosionSize>%d</explosionSize>\r\n", AmmoTypes[cnt].explosionSize );
FilePrintf(hFile,"\t\t<antiTank>%d</antiTank>\r\n", AmmoTypes[cnt].antiTank );
FilePrintf(hFile,"\t\t<dart>%d</dart>\r\n", AmmoTypes[cnt].dart );
FilePrintf(hFile,"\t\t<knife>%d</knife>\r\n", AmmoTypes[cnt].knife );
FilePrintf(hFile,"\t\t<monsterSpit>%d</monsterSpit>\r\n", AmmoTypes[cnt].monsterSpit );
FilePrintf(hFile,"\t\t<acidic>%d</acidic>\r\n", AmmoTypes[cnt].acidic );
FilePrintf(hFile,"\t\t<ignoreArmour>%d</ignoreArmour>\r\n", AmmoTypes[cnt].ignoreArmour );
FilePrintf(hFile,"\t\t<lockBustingPower>%d</lockBustingPower>\r\n", AmmoTypes[cnt].lockBustingPower );
FilePrintf(hFile,"\t\t<tracerEffect>%d</tracerEffect>\r\n", AmmoTypes[cnt].tracerEffect );
FilePrintf(hFile,"\t\t<temperatureModificator>%4.2f</temperatureModificator>\r\n", AmmoTypes[cnt].temperatureModificator );
FilePrintf(hFile,"\t\t<PoisonPercentage>%d</PoisonPercentage>\r\n", AmmoTypes[cnt].poisonPercentage );
FilePrintf(hFile,"\t\t<uiIndex>%d</uiIndex>\r\n", cnt );
FilePrintf(hFile,"\t\t<fontColour>%d</fontColour>\r\n", AmmoTypes[cnt].fontColour );
FilePrintf(hFile,"\t\t<grayed>%d</grayed>\r\n", AmmoTypes[cnt].grayed );
FilePrintf(hFile,"\t\t<offNormal>%d</offNormal>\r\n", AmmoTypes[cnt].offNormal );
FilePrintf(hFile,"\t\t<onNormal>%d</onNormal>\r\n", AmmoTypes[cnt].onNormal );
FilePrintf(hFile,"\t\t<structureImpactReductionMultiplier>%d</structureImpactReductionMultiplier>\r\n", AmmoTypes[cnt].structureImpactReductionMultiplier );
FilePrintf(hFile,"\t\t<structureImpactReductionDivisor>%d</structureImpactReductionDivisor>\r\n", AmmoTypes[cnt].structureImpactReductionDivisor );
FilePrintf(hFile,"\t\t<armourImpactReductionMultiplier>%d</armourImpactReductionMultiplier>\r\n", AmmoTypes[cnt].armourImpactReductionMultiplier );
FilePrintf(hFile,"\t\t<armourImpactReductionDivisor>%d</armourImpactReductionDivisor>\r\n", AmmoTypes[cnt].armourImpactReductionDivisor );
FilePrintf(hFile,"\t\t<beforeArmourDamageMultiplier>%d</beforeArmourDamageMultiplier>\r\n", AmmoTypes[cnt].beforeArmourDamageMultiplier );
FilePrintf(hFile,"\t\t<beforeArmourDamageDivisor>%d</beforeArmourDamageDivisor>\r\n", AmmoTypes[cnt].beforeArmourDamageDivisor );
FilePrintf(hFile,"\t\t<afterArmourDamageMultiplier>%d</afterArmourDamageMultiplier>\r\n", AmmoTypes[cnt].afterArmourDamageMultiplier );
FilePrintf(hFile,"\t\t<afterArmourDamageDivisor>%d</afterArmourDamageDivisor>\r\n", AmmoTypes[cnt].afterArmourDamageDivisor );
FilePrintf(hFile,"\t\t<zeroMinimumDamage>%d</zeroMinimumDamage>\r\n", AmmoTypes[cnt].zeroMinimumDamage );
FilePrintf(hFile,"\t\t<canGoThrough>%d</canGoThrough>\r\n", AmmoTypes[cnt].canGoThrough );
FilePrintf(hFile,"\t\t<standardIssue>%d</standardIssue>\r\n", AmmoTypes[cnt].standardIssue );
FilePrintf(hFile,"\t\t<numberOfBullets>%d</numberOfBullets>\r\n", AmmoTypes[cnt].numberOfBullets );
FilePrintf(hFile,"\t\t<multipleBulletDamageMultiplier>%d</multipleBulletDamageMultiplier>\r\n", AmmoTypes[cnt].multipleBulletDamageMultiplier );
FilePrintf(hFile,"\t\t<multipleBulletDamageDivisor>%d</multipleBulletDamageDivisor>\r\n", AmmoTypes[cnt].multipleBulletDamageDivisor );
FilePrintf(hFile,"\t\t<highExplosive>%d</highExplosive>\r\n", AmmoTypes[cnt].highExplosive );
FilePrintf(hFile,"\t\t<explosionSize>%d</explosionSize>\r\n", AmmoTypes[cnt].explosionSize );
FilePrintf(hFile,"\t\t<antiTank>%d</antiTank>\r\n", AmmoTypes[cnt].antiTank );
FilePrintf(hFile,"\t\t<dart>%d</dart>\r\n", AmmoTypes[cnt].dart );
FilePrintf(hFile,"\t\t<knife>%d</knife>\r\n", AmmoTypes[cnt].knife );
FilePrintf(hFile,"\t\t<monsterSpit>%d</monsterSpit>\r\n", AmmoTypes[cnt].monsterSpit );
FilePrintf(hFile,"\t\t<acidic>%d</acidic>\r\n", AmmoTypes[cnt].acidic );
FilePrintf(hFile,"\t\t<ignoreArmour>%d</ignoreArmour>\r\n", AmmoTypes[cnt].ignoreArmour );
FilePrintf(hFile,"\t\t<lockBustingPower>%d</lockBustingPower>\r\n", AmmoTypes[cnt].lockBustingPower );
FilePrintf(hFile,"\t\t<tracerEffect>%d</tracerEffect>\r\n", AmmoTypes[cnt].tracerEffect );
FilePrintf(hFile,"\t\t<temperatureModificator>%4.2f</temperatureModificator>\r\n", AmmoTypes[cnt].temperatureModificator );
FilePrintf(hFile,"\t\t<PoisonPercentage>%d</PoisonPercentage>\r\n", AmmoTypes[cnt].poisonPercentage );
FilePrintf(hFile,"\t\t<dirtModificator>%4.2f</dirtModificator>\r\n", AmmoTypes[cnt].dirtModificator );
FilePrintf(hFile,"\t\t<ammoflag>%d</ammoflag>\r\n", AmmoTypes[cnt].ammoflag );
FilePrintf(hFile,"\t</AMMOTYPE>\r\n");
}
+47 -33
View File
@@ -446,7 +446,7 @@ void ReevaluateBestSightingPosition( SOLDIERTYPE * pSoldier, INT8 bInterruptDuel
{
for ( ubLoop = 0; ubLoop < gubBestToMakeSightingSize; ubLoop++ )
{
if ( (gubBestToMakeSighting[ ubLoop ] == NOBODY) || (bInterruptDuelPts > MercPtrs[ gubBestToMakeSighting[ ubLoop ] ]->aiData.bInterruptDuelPts ) )
if ( pSoldier->RecognizeAsCombatant(gubBestToMakeSighting[ ubLoop ]) && (gubBestToMakeSighting[ ubLoop ] == NOBODY) || (bInterruptDuelPts > MercPtrs[ gubBestToMakeSighting[ ubLoop ] ]->aiData.bInterruptDuelPts ) )
{
if ( gubBestToMakeSighting[ gubBestToMakeSightingSize - 1 ] != NOBODY )
{
@@ -509,36 +509,43 @@ void HandleBestSightingPositionInRealtime( void )
if (gubBestToMakeSighting[ 1 ] == NOBODY)
{ // The_Bob - real time sneaking code 01/06/09
// if real time sneaking conditions are met...
// this is now in the preferences window - SANDRO
// this is now in the preferences window - SANDRO
if (gGameSettings.fOptions[TOPTION_ALLOW_REAL_TIME_SNEAK] && MercPtrs[gubBestToMakeSighting[ 0 ]]->bTeam == OUR_TEAM && NobodyAlerted() )
{
// get rid of the item under cursor (we gotta react FAST)
CancelItemPointer();
// select (and center screen on) the merc who saw the enemy
// HEADROCK HAM 3.6: A much-requested toggle.
if (gusSelectedSoldier != (UINT16)MercPtrs[gubBestToMakeSighting[ 0 ]]->ubID &&
!gGameExternalOptions.fNoAutoFocusChangeInRealtimeSneak)
SelectSoldier (MercPtrs[gubBestToMakeSighting[ 0 ]]->ubID, false, true);
// if not quiet, emit a message warning the player
if (!gGameExternalOptions.fQuietRealTimeSneak)
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_RTM_ENEMIES_SPOOTED]);
{
// get rid of the item under cursor (we gotta react FAST)
CancelItemPointer();
// select (and center screen on) the merc who saw the enemy
// HEADROCK HAM 3.6: A much-requested toggle.
if (gusSelectedSoldier != (UINT16)MercPtrs[gubBestToMakeSighting[ 0 ]]->ubID &&
!gGameExternalOptions.fNoAutoFocusChangeInRealtimeSneak)
SelectSoldier (MercPtrs[gubBestToMakeSighting[ 0 ]]->ubID, false, true);
// if not quiet, emit a message warning the player
if (!gGameExternalOptions.fQuietRealTimeSneak)
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_RTM_ENEMIES_SPOOTED]);
return; // and do nothing
}
return; // and do nothing
}
else if ( MercPtrs[gubBestToMakeSighting[ 0 ]]->bTeam != OUR_TEAM && MercPtrs[gubBestToMakeSighting[ 0 ]]->aiData.bOppCnt > 0 )
{
// otherwise, simply award the turn to the team that saw the enemy first
EnterCombatMode( MercPtrs[gubBestToMakeSighting[ 0 ]]->bTeam );
}
else
// otherwise, simply award the turn to the team that saw the enemy first
EnterCombatMode( MercPtrs[gubBestToMakeSighting[ 0 ]]->bTeam );
}
else
{
// if 1st and 2nd on same team, or 1st and 3rd on same team, or there IS no 3rd, award turn to 1st
if ( ( MercPtrs[gubBestToMakeSighting[ 0 ]]->bTeam == MercPtrs[gubBestToMakeSighting[ 1 ]]->bTeam ) ||
if ( /*MercPtrs[gubBestToMakeSighting[ 0 ]]->aiData.bOppCnt > 0 &&*/ ( MercPtrs[gubBestToMakeSighting[ 0 ]]->bTeam == MercPtrs[gubBestToMakeSighting[ 1 ]]->bTeam ) ||
( (gubBestToMakeSighting[ 2 ] == NOBODY) || ( MercPtrs[gubBestToMakeSighting[ 0 ]]->bTeam == MercPtrs[gubBestToMakeSighting[ 2 ]]->bTeam ) )
)
{
EnterCombatMode( MercPtrs[gubBestToMakeSighting[ 0 ]]->bTeam );
}
else // give turn to 2nd best but interrupt to 1st
else //if ( MercPtrs[gubBestToMakeSighting[ 1 ]]->aiData.bOppCnt > 0 ) // give turn to 2nd best but interrupt to 1st
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Entering combat mode: turn for 2nd best, int for best" );
@@ -1766,7 +1773,7 @@ void HandleManNoLongerSeen( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pOpponent, INT
{
// if neither side is neutral AND
// if this soldier is an opponent (fights for different side)
if (pSoldier->bActive && pOpponent->bActive && !CONSIDERED_NEUTRAL( pOpponent, pSoldier ) && !CONSIDERED_NEUTRAL( pSoldier, pOpponent ) && (pSoldier->bSide != pOpponent->bSide))
if (pSoldier->bActive && pOpponent->bActive && !CONSIDERED_NEUTRAL( pOpponent, pSoldier ) && !CONSIDERED_NEUTRAL( pSoldier, pOpponent ) && (pSoldier->bSide != pOpponent->bSide) && pSoldier->RecognizeAsCombatant(pOpponent->ubID) )
{
RemoveOneOpponent(pSoldier);
}
@@ -2199,6 +2206,9 @@ void ManSeesMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, INT32 sOppGridNo,
return;
}
// Flugente: update our sight concerning this guy, otherwise we could get way with open attacks because this does not get updated
pSoldier->RecognizeAsCombatant(pOpponent->ubID);
// if we're seeing a guy we didn't see on our last chance to look for him
if (pSoldier->aiData.bOppList[pOpponent->ubID] != SEEN_CURRENTLY)
{
@@ -2503,7 +2513,7 @@ void ManSeesMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, INT32 sOppGridNo,
// if both of us are not neutral, AND
// if this man is actually a true opponent (we're not on the same side)
if (!CONSIDERED_NEUTRAL( pOpponent, pSoldier ) && !CONSIDERED_NEUTRAL( pSoldier, pOpponent ) && (pSoldier->bSide != pOpponent->bSide))
if (!CONSIDERED_NEUTRAL( pOpponent, pSoldier ) && !CONSIDERED_NEUTRAL( pSoldier, pOpponent ) && (pSoldier->bSide != pOpponent->bSide) && pSoldier->RecognizeAsCombatant(pOpponent->ubID) )
{
AddOneOpponent(pSoldier);
@@ -3002,7 +3012,7 @@ IAN COMMENTED THIS OUT MAY 1997 - DO WE NEED THIS?
if (pOpponent)
{
// check to see if OPPONENT considers US neutral
if ( (pOpponent->aiData.bOppList[ubTarget] == SEEN_CURRENTLY) && !pOpponent->aiData.bNeutral && !CONSIDERED_NEUTRAL( pOpponent, pSoldier ) && (pSoldier->bSide != pOpponent->bSide) )
if ( (pOpponent->aiData.bOppList[ubTarget] == SEEN_CURRENTLY) && !pOpponent->aiData.bNeutral && !CONSIDERED_NEUTRAL( pOpponent, pSoldier ) && (pSoldier->bSide != pOpponent->bSide) && pOpponent->RecognizeAsCombatant(pSoldier->ubID) )
{
RemoveOneOpponent(pOpponent);
}
@@ -3501,20 +3511,24 @@ void SaySeenQuote( SOLDIERTYPE *pSoldier, BOOLEAN fSeenCreature, BOOLEAN fVirgin
}
else
{
// Flugente: no quotes on seeing enemy when covert
if ( (pSoldier->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER) ) == 0 )
{
#ifdef ENGLISH
if ( Random( 100 ) < 30 )
{
pSoldier->DoMercBattleSound( BATTLE_SOUND_ENEMY );
}
else
{
TacticalCharacterDialogue( pSoldier, QUOTE_SEE_ENEMY );
}
if ( Random( 100 ) < 30 )
{
pSoldier->DoMercBattleSound( BATTLE_SOUND_ENEMY );
}
else
{
TacticalCharacterDialogue( pSoldier, QUOTE_SEE_ENEMY );
}
#else
//ddd TacticalCharacterDialogue( pSoldier, QUOTE_SEE_ENEMY );
if(Chance(gGameExternalOptions.iChanceSayAnnoyingPhrase) )
TacticalCharacterDialogue( pSoldier, QUOTE_SEE_ENEMY );
//ddd TacticalCharacterDialogue( pSoldier, QUOTE_SEE_ENEMY );
if(Chance(gGameExternalOptions.iChanceSayAnnoyingPhrase) )
TacticalCharacterDialogue( pSoldier, QUOTE_SEE_ENEMY );
#endif
}
}
}
}
@@ -6821,7 +6835,7 @@ void DecayIndividualOpplist(SOLDIERTYPE *pSoldier)
{
// they are NOT visible now!
(*pPersOL)++;
if (!CONSIDERED_NEUTRAL( pOpponent, pSoldier ) && !CONSIDERED_NEUTRAL( pSoldier, pOpponent ) && (pSoldier->bSide != pOpponent->bSide))
if (!CONSIDERED_NEUTRAL( pOpponent, pSoldier ) && !CONSIDERED_NEUTRAL( pSoldier, pOpponent ) && (pSoldier->bSide != pOpponent->bSide) && pSoldier->RecognizeAsCombatant(pOpponent->ubID) )
{
RemoveOneOpponent(pSoldier);
}
@@ -7084,7 +7098,7 @@ void RecalculateOppCntsDueToBecomingNeutral( SOLDIERTYPE * pSoldier )
pOpponent = MercSlots[uiLoop];
// for every active, living soldier on ANOTHER team
if (pOpponent && pOpponent->stats.bLife && !pOpponent->aiData.bNeutral && (pOpponent->bTeam != pSoldier->bTeam) && !CONSIDERED_NEUTRAL( pSoldier, pOpponent ) && (pSoldier->bSide != pOpponent->bSide) )
if (pOpponent && pOpponent->stats.bLife && !pOpponent->aiData.bNeutral && (pOpponent->bTeam != pSoldier->bTeam) && !CONSIDERED_NEUTRAL( pSoldier, pOpponent ) && (pSoldier->bSide != pOpponent->bSide) && pSoldier->RecognizeAsCombatant(pOpponent->ubID) )
{
if ( pOpponent->aiData.bOppList[pSoldier->ubID] == SEEN_CURRENTLY )
{
+10 -1
View File
@@ -157,12 +157,21 @@ typedef enum
DEMOLITIONS_NT, // 17
TEACHING_NT, // 18
SCOUTING_NT, // 19
// Flugente: new traits have to go here, even if they are major traits, as otherwise the existing traits in profiles get mixed up
COVERT_NT, // 20
NUM_SKILLTRAITS_NT
} SkillTraitNew;
#define NUM_MAJOR_TRAITS 9
#define NUM_MAJOR_TRAITS 10
#define NUM_MINOR_TRAITS 10
// Flugente: I've had it with this hardcoding madness. Without this, adding or removing a new trait would crash anything related to a bubblehelp display of traits
// always check every use of these enums and every use of the skill-strings if you add a new trait
#define NEWTRAIT_MERCSKILL_EXPERTOFFSET NUM_MAJOR_TRAITS + NUM_MINOR_TRAITS
#define NEWTRAIT_MERCSKILL_OFFSET_ALL NEWTRAIT_MERCSKILL_EXPERTOFFSET + NUM_MAJOR_TRAITS
// SANDRO - new set of character traits
typedef enum
{
+9
View File
@@ -189,6 +189,15 @@ INT32 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
if ( CONSIDERED_NEUTRAL( pSoldier, pTemp ) || (pSoldier->bSide == pTemp->bSide))
continue; // next merc
// Flugente: chance to ignore the noise if the ceator is covert
if ( pTemp->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER) )
{
// green AI state: always ignore
// yellow AI state: 50% chance to ignore
if ( pSoldier->aiData.bAlertStatus == STATUS_GREEN || (pSoldier->aiData.bAlertStatus == STATUS_GREEN && Random(2) < 1 ) )
continue; // next merc
}
pbPersOL = pSoldier->aiData.bOppList + pTemp->ubID;
pbPublOL = gbPublicOpplist[pSoldier->bTeam] + pTemp->ubID;
psLastLoc = gsLastKnownOppLoc[pSoldier->ubID] + pTemp->ubID;
+4 -2
View File
@@ -640,8 +640,8 @@ extern STR16 szUDBGenAmmoStatsTooltipText[ 6 ]; // Flugente Overheating: 3
extern STR16 szUDBGenAmmoStatsExplanationsTooltipText[ 6 ]; // Flugente Overheating: 3->4 poison: 4->5 dirt: 5->6
extern STR16 szUDBGenExplosiveStatsTooltipText[ 22 ];
extern STR16 szUDBGenExplosiveStatsExplanationsTooltipText[ 22 ];
extern STR16 szUDBGenSecondaryStatsTooltipText[ 31 ]; // Flugente Food System: 26 -> 28 external feeding: 28->30 JMich_SkillsModifiers: 31 for Defusal kit
extern STR16 szUDBGenSecondaryStatsExplanationsTooltipText[ 31 ]; // Flugente Food System: 26 -> 28 external feeding: 28->30 JMich_SkillsModifiers: 31 for Defusal kit
extern STR16 szUDBGenSecondaryStatsTooltipText[ 32 ]; // Flugente Food System: 26 -> 28 external feeding: 28->30 JMich_SkillsModifiers: 31 for Defusal kit - covert item: 31->32
extern STR16 szUDBGenSecondaryStatsExplanationsTooltipText[ 32 ]; // Flugente Food System: 26 -> 28 external feeding: 28->30 JMich_SkillsModifiers: 31 for Defusal kit - covert item: 31->32
extern STR16 szUDBAdvStatsTooltipText[ 58 ]; // Flugente Overheating Weapons: 48->56 poison: 56->57 dirt: 57->58
extern STR16 szUDBAdvStatsExplanationsTooltipText[ 58 ]; // Flugente Overheating Weapons: 48->56 poison: 56->57 dirt: 57->58
extern STR16 szUDBAdvStatsExplanationsTooltipTextForWeapons[ 52 ]; // Flugente Overheating Weapons: 48->52
@@ -819,6 +819,8 @@ enum
MERC_VITAL_STATS_WITH_POISON_AND_FOOD_POPUPTEXT,
FUNCTION_SELECTION_STR,
CORPSE_SELECTION_STR,
TEXT_NUM_TACTICAL_STR
};
+2
View File
@@ -7084,6 +7084,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|A|m|m|o |B|e|l|t",
L"|A|m|m|o |V|e|s|t",
L"|D|e|f|u|s|a|l |K|i|t", // TODO.Translate
L"|C|o|v|e|r|t |I|t|e|m",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -7119,6 +7120,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nWith this ammo belt you can\nfeed someone else's MG.",
L"\n \nYou can feed an MG with ammo\nbelts stored in this vest.",
L"\n \nThis item improves your trap disarm chance by ", // TODO.Translate
L"\n \nThis item and everything attached/inside\nit is hidden from curious eyes.",
};
STR16 szUDBAdvStatsTooltipText[]=
+2
View File
@@ -7075,6 +7075,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|A|m|m|o |B|e|l|t",
L"|A|m|m|o |V|e|s|t",
L"|D|e|f|u|s|a|l |K|i|t", // TODO.Translate
L"|C|o|v|e|r|t |I|t|e|m",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -7110,6 +7111,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nWith this ammo belt you can\nfeed someone else's MG.",
L"\n \nYou can feed an MG with ammo\nbelts stored in this vest.",
L"\n \nThis item improves your trap disarm chance by ", // TODO.Translate
L"\n \nThis item and everything attached/inside\nit is hidden from curious eyes.",
};
STR16 szUDBAdvStatsTooltipText[]=
+15 -6
View File
@@ -2104,37 +2104,39 @@ STR16 gzMercSkillText[] =
STR16 gzMercSkillTextNew[] =
{
// Major traits
L"No Skill",
L"No Skill", // 0
L"Auto Weapons",
L"Heavy Weapons",
L"Marksman",
L"Hunter",
L"Gunslinger",
L"Gunslinger", // 5
L"Hand to Hand",
L"Deputy",
L"Technician",
L"Paramedic",
L"Covert Ops", // 10
// Minor traits
L"Ambidextrous",
L"Melee",
L"Throwing",
L"Night Ops",
L"Stealthy",
L"Stealthy", // 15
L"Athletics",
L"Bodybuilding",
L"Demolitions",
L"Teaching",
L"Scouting",
L"Scouting", // 20
// second names for major skills
L"Machinegunner",
L"Bombardier",
L"Sniper",
L"Ranger",
L"Gunfighter",
L"Gunfighter", // 25
L"Martial Arts",
L"Squadleader",
L"Engineer",
L"Doctor",
L"Spy", // 30
L"More...",
};
//////////////////////////////////////////////////////////
@@ -2936,6 +2938,9 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
// added by Flugente: selection of a function to call in tactical
L"1 - Fill Canteens 2 - Clean Weapons 3,4 - Nothing",
// added by Flugente: decide what to do with the corpses
L"1 - Decapitate 2 - Gut 3 - Take Clothes 4 - Take Body",
};
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
@@ -6300,7 +6305,9 @@ STR16 MissingIMPSkillsDescriptions[] =
// Demolitions
L"Demolitions: Sowing grenades like seeds, planting bombs, watching the limbs flying.. This is what you live for! ± ",
// Scouting
L"Scouting: Nothing can escape your notice! ± ",
L"Scouting: Nothing can escape your notice! ± ",
// Covert ops
L"Covert Operations: You make 007 look like an amateur! ± ",
};
STR16 NewInvMessage[] =
@@ -7067,6 +7074,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|A|m|m|o |B|e|l|t",
L"|A|m|m|o |V|e|s|t",
L"|D|e|f|u|s|a|l |K|i|t",
L"|C|o|v|e|r|t |I|t|e|m",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -7102,6 +7110,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nWith this ammo belt you can\nfeed someone else's MG.",
L"\n \nYou can feed an MG with ammo\nbelts stored in this vest.",
L"\n \nThis item improves your trap disarm chance by ",
L"\n \nThis item and everything attached/inside\nit is hidden from curious eyes.",
};
STR16 szUDBAdvStatsTooltipText[]=
+2
View File
@@ -7050,6 +7050,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|A|m|m|o |B|e|l|t",
L"|A|m|m|o |V|e|s|t",
L"|D|e|f|u|s|a|l |K|i|t", // TODO.Translate
L"|C|o|v|e|r|t |I|t|e|m",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -7085,6 +7086,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nWith this ammo belt you can\nfeed someone else's MG.",
L"\n \nYou can feed an MG with ammo\nbelts stored in this vest.",
L"\n \nThis item improves your trap disarm chance by ", // TODO.Translate
L"\n \nThis item and everything attached/inside\nit is hidden from curious eyes.",
};
STR16 szUDBAdvStatsTooltipText[]=
+2
View File
@@ -6894,6 +6894,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|M|u|n|i|t|i|o|n|s|g|u|r|t",
L"|M|u|n|i|t|i|o|n|s|w|e|s|t|e",
L"|D|e|f|u|s|a|l |K|i|t", // TODO.Translate
L"|C|o|v|e|r|t |I|t|e|m",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -6929,6 +6930,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nEin externer Munitionsgurt für MGs.",
L"\n \nIn diese Weste passen auch Munitionsgurte.",
L"\n \nThis item improves your trap disarm chance by ", // TODO.Translate
L"\n \nThis item and everything attached/inside\nit is hidden from curious eyes.",
};
STR16 szUDBAdvStatsTooltipText[]=
+2
View File
@@ -7062,6 +7062,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|A|m|m|o |B|e|l|t",
L"|A|m|m|o |V|e|s|t",
L"|D|e|f|u|s|a|l |K|i|t", // TODO.Translate
L"|C|o|v|e|r|t |I|t|e|m",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -7097,6 +7098,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nWith this ammo belt you can\nfeed someone else's MG.",
L"\n \nYou can feed an MG with ammo\nbelts stored in this vest.",
L"\n \nThis item improves your trap disarm chance by ", // TODO.Translate
L"\n \nThis item and everything attached/inside\nit is hidden from curious eyes.",
};
STR16 szUDBAdvStatsTooltipText[]=
+12
View File
@@ -58,6 +58,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"班副",// L"Deputy",
L"技师",// L"Technician",
L"救护员",// L"Paramedic",
L"Covert Ops", // TODO.Translate
L"",// L"None",
L"I.M.P 主要特殊技能",// L"I.M.P. Major Traits",
@@ -71,6 +72,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"班长",// L"Squadleader",
L"工兵",// L"Engineer",
L"军医",// L"Doctor",
L"Spy", // TODO.Translate
};
//added another set of skill texts for new minor traits
@@ -241,6 +243,16 @@ STR16 gzIMPMajorTraitsHelpTextsDoctor[]=
L"(这种效果最多叠加 %d 次)",// L" (max %d these bonuses per sector)",
};
STR16 gzIMPMajorTraitsHelpTextsCovertOps[]= // TODO.Translate
{
L"Can disguise as a civilian or soldier to slip behind enemy lines.\n",
L"Will be detected if performing suspicious actions, having\nsuspicious gear or being near fresh corpses.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to the enemy.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to a fresh corpse.\n",
L"+%d%s CTH with covert melee weapons\n",
L"+%d%s chance of instakill with covert melee weapons\n",
L"Disguise AP cost lowered by %d%s.\n",
};
STR16 gzIMPMajorTraitsHelpTextsNone[]=
{
L"无奖励",// L"No bonuses",
+12
View File
@@ -58,6 +58,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"Deputy",
L"Technician",
L"Paramedic",
L"Covert Ops", // TODO.Translate
L"None",
L"I.M.P. Major Traits",
@@ -71,6 +72,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"Squadleader",
L"Engineer",
L"Doctor",
L"Spy", // TODO.Translate
};
//added another set of skill texts for new minor traits
@@ -240,6 +242,16 @@ STR16 gzIMPMajorTraitsHelpTextsDoctor[]=
L" (max %d these bonuses per sector)",
};
STR16 gzIMPMajorTraitsHelpTextsCovertOps[]= // TODO.Translate
{
L"Can disguise as a civilian or soldier to slip behind enemy lines.\n",
L"Will be detected if performing suspicious actions, having\nsuspicious gear or being near fresh corpses.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to the enemy.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to a fresh corpse.\n",
L"+%d%s CTH with covert melee weapons\n",
L"+%d%s chance of instakill with covert melee weapons\n",
L"Disguise AP cost lowered by %d%s.\n",
};
STR16 gzIMPMajorTraitsHelpTextsNone[]=
{
L"No bonuses",
+1
View File
@@ -17,6 +17,7 @@ extern STR16 gzIMPMajorTraitsHelpTextsMartialArts[];
extern STR16 gzIMPMajorTraitsHelpTextsSquadleader[];
extern STR16 gzIMPMajorTraitsHelpTextsTechnician[];
extern STR16 gzIMPMajorTraitsHelpTextsDoctor[];
extern STR16 gzIMPMajorTraitsHelpTextsCovertOps[]; // added by Flugente
extern STR16 gzIMPMajorTraitsHelpTextsNone[];
extern STR16 gzIMPMinorTraitsHelpTextsAmbidextrous[];
+12 -1
View File
@@ -58,6 +58,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"Deputy",
L"Technician",
L"Paramedic",
L"Covert Ops",
L"None",
L"I.M.P. Major Traits",
@@ -71,6 +72,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"Squadleader",
L"Engineer",
L"Doctor",
L"Spy",
};
//added another set of skill texts for new minor traits
@@ -238,7 +240,16 @@ STR16 gzIMPMajorTraitsHelpTextsDoctor[]=
L"+%d%s bandaging speed\n",
L"+%d%s natural regeneration speed for all soldiers in the same sector", // MINTY - Changed "of" to "for"
L" (max %d of these bonuses per sector stack)",
};
STR16 gzIMPMajorTraitsHelpTextsCovertOps[]=
{
L"Can disguise as a civilian or soldier to slip behind enemy lines.\n",
L"Will be detected if performing suspicious actions, having\nsuspicious gear or being near fresh corpses.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to the enemy.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to a fresh corpse.\n",
L"+%d%s CTH with covert melee weapons\n",
L"+%d%s chance of instakill with covert melee weapons\n",
L"Disguise AP cost lowered by %d%s.\n",
};
STR16 gzIMPMajorTraitsHelpTextsNone[]=
{
+1
View File
@@ -17,6 +17,7 @@ extern STR16 gzIMPMajorTraitsHelpTextsMartialArts[];
extern STR16 gzIMPMajorTraitsHelpTextsSquadleader[];
extern STR16 gzIMPMajorTraitsHelpTextsTechnician[];
extern STR16 gzIMPMajorTraitsHelpTextsDoctor[];
extern STR16 gzIMPMajorTraitsHelpTextsCovertOps[]; // added by Flugente
extern STR16 gzIMPMajorTraitsHelpTextsNone[];
extern STR16 gzIMPMinorTraitsHelpTextsAmbidextrous[];
+12
View File
@@ -58,6 +58,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"Manager",
L"Technicien",
L"Médecin",
L"Covert Ops", // TODO.Translate
L"Personne",
L"I.M.P. Traits pincipaux",
@@ -71,6 +72,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"Commandant",
L"Ingénieur",
L"Chirurgien",
L"Spy", // TODO.Translate
};
//added another set of skill texts for new minor traits
@@ -241,6 +243,16 @@ STR16 gzIMPMajorTraitsHelpTextsDoctor[]=
L" (un maximum de %d bonus par secteur)",
};
STR16 gzIMPMajorTraitsHelpTextsCovertOps[]= // TODO.Translate
{
L"Can disguise as a civilian or soldier to slip behind enemy lines.\n",
L"Will be detected if performing suspicious actions, having\nsuspicious gear or being near fresh corpses.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to the enemy.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to a fresh corpse.\n",
L"+%d%s CTH with covert melee weapons\n",
L"+%d%s chance of instakill with covert melee weapons\n",
L"Disguise AP cost lowered by %d%s.\n",
};
STR16 gzIMPMajorTraitsHelpTextsNone[]=
{
L"Pas de bonus",
+1
View File
@@ -17,6 +17,7 @@ extern STR16 gzIMPMajorTraitsHelpTextsMartialArts[];
extern STR16 gzIMPMajorTraitsHelpTextsSquadleader[];
extern STR16 gzIMPMajorTraitsHelpTextsTechnician[];
extern STR16 gzIMPMajorTraitsHelpTextsDoctor[];
extern STR16 gzIMPMajorTraitsHelpTextsCovertOps[]; // added by Flugente
extern STR16 gzIMPMajorTraitsHelpTextsNone[];
extern STR16 gzIMPMinorTraitsHelpTextsAmbidextrous[];
+12
View File
@@ -54,6 +54,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"Gruppenführer", //GrpFhr und ZgFhr sind scheiße, aber mir fällt ohne Dienstgrade nüscht ein
L"Mechaniker", //Option: Techniker
L"Sanitäter", //Option: Rettungsassistent
L"Covert Ops", // TODO.Translate
L"Nichts",
L"B.S.E. Hauptfertigkeiten",
@@ -68,6 +69,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"Zugführer",
L"Ingenieur",
L"Arzt",
L"Spy", // TODO.Translate
};
//added another set of skill texts for new minor traits
@@ -239,6 +241,16 @@ STR16 gzIMPMajorTraitsHelpTextsDoctor[]=
L" (maximal %d Instanzen dieses Bonus pro Sektor)",
};
STR16 gzIMPMajorTraitsHelpTextsCovertOps[]= // TODO.Translate
{
L"Can disguise as a civilian or soldier to slip behind enemy lines.\n",
L"Will be detected if performing suspicious actions, having\nsuspicious gear or being near fresh corpses.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to the enemy.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to a fresh corpse.\n",
L"+%d%s CTH with covert melee weapons\n",
L"+%d%s chance of instakill with covert melee weapons\n",
L"Disguise AP cost lowered by %d%s.\n",
};
STR16 gzIMPMajorTraitsHelpTextsNone[]=
{
L"Keine Boni",
+1
View File
@@ -17,6 +17,7 @@ extern STR16 gzIMPMajorTraitsHelpTextsMartialArts[];
extern STR16 gzIMPMajorTraitsHelpTextsSquadleader[];
extern STR16 gzIMPMajorTraitsHelpTextsTechnician[];
extern STR16 gzIMPMajorTraitsHelpTextsDoctor[];
extern STR16 gzIMPMajorTraitsHelpTextsCovertOps[]; // added by Flugente
extern STR16 gzIMPMajorTraitsHelpTextsNone[];
extern STR16 gzIMPMinorTraitsHelpTextsAmbidextrous[];
+12
View File
@@ -56,6 +56,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"Deputy",
L"Technician",
L"Paramedic",
L"Covert Ops", // TODO.Translate
L"None",
L"I.M.P. Major Traits",
@@ -69,6 +70,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"Squadleader",
L"Engineer",
L"Doctor",
L"Spy", // TODO.Translate
};
//added another set of skill texts for new minor traits
@@ -239,6 +241,16 @@ STR16 gzIMPMajorTraitsHelpTextsDoctor[]=
L" (max %d these bonuses per sector)",
};
STR16 gzIMPMajorTraitsHelpTextsCovertOps[]= // TODO.Translate
{
L"Can disguise as a civilian or soldier to slip behind enemy lines.\n",
L"Will be detected if performing suspicious actions, having\nsuspicious gear or being near fresh corpses.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to the enemy.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to a fresh corpse.\n",
L"+%d%s CTH with covert melee weapons\n",
L"+%d%s chance of instakill with covert melee weapons\n",
L"Disguise AP cost lowered by %d%s.\n",
};
STR16 gzIMPMajorTraitsHelpTextsNone[]=
{
L"No bonuses",
+1
View File
@@ -17,6 +17,7 @@ extern STR16 gzIMPMajorTraitsHelpTextsMartialArts[];
extern STR16 gzIMPMajorTraitsHelpTextsSquadleader[];
extern STR16 gzIMPMajorTraitsHelpTextsTechnician[];
extern STR16 gzIMPMajorTraitsHelpTextsDoctor[];
extern STR16 gzIMPMajorTraitsHelpTextsCovertOps[]; // added by Flugente
extern STR16 gzIMPMajorTraitsHelpTextsNone[];
extern STR16 gzIMPMinorTraitsHelpTextsAmbidextrous[];
+12
View File
@@ -58,6 +58,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"Zastępca szeryfa",
L"Technik",
L"Paramedyk",
L"Covert Ops", // TODO.Translate
L"None",
L"Główne cechy I.M.P",
@@ -71,6 +72,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"Dowódca drużyny",
L"Inżynier",
L"Doktor",
L"Spy", // TODO.Translate
};
//added another set of skill texts for new minor traits
@@ -241,6 +243,16 @@ STR16 gzIMPMajorTraitsHelpTextsDoctor[]=
L" (max %d of these bonuses per sector stack)",
};
STR16 gzIMPMajorTraitsHelpTextsCovertOps[]= // TODO.Translate
{
L"Can disguise as a civilian or soldier to slip behind enemy lines.\n",
L"Will be detected if performing suspicious actions, having\nsuspicious gear or being near fresh corpses.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to the enemy.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to a fresh corpse.\n",
L"+%d%s CTH with covert melee weapons\n",
L"+%d%s chance of instakill with covert melee weapons\n",
L"Disguise AP cost lowered by %d%s.\n",
};
STR16 gzIMPMajorTraitsHelpTextsNone[]=
{
L"No bonuses",
+1
View File
@@ -17,6 +17,7 @@ extern STR16 gzIMPMajorTraitsHelpTextsMartialArts[];
extern STR16 gzIMPMajorTraitsHelpTextsSquadleader[];
extern STR16 gzIMPMajorTraitsHelpTextsTechnician[];
extern STR16 gzIMPMajorTraitsHelpTextsDoctor[];
extern STR16 gzIMPMajorTraitsHelpTextsCovertOps[]; // added by Flugente
extern STR16 gzIMPMajorTraitsHelpTextsNone[];
extern STR16 gzIMPMinorTraitsHelpTextsAmbidextrous[];
+12
View File
@@ -57,6 +57,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"Старшина", //Deputy
L"Механик-электронщик", //Technician
L"Санитар", //Paramedic
L"Covert Ops", // TODO.Translate
L"Нет",
L"I.M.P.: Основные навыки", //I.M.P. Major Traits
@@ -70,6 +71,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"Командир", //Squadleader
L"Инженер", //Engineer
L"Доктор", //Doctor
L"Spy", // TODO.Translate
};
//added another set of skill texts for new minor traits
@@ -240,6 +242,16 @@ STR16 gzIMPMajorTraitsHelpTextsDoctor[]=
L" (максимум %d бонуса на находящихся в секторе)",
};
STR16 gzIMPMajorTraitsHelpTextsCovertOps[]= // TODO.Translate
{
L"Can disguise as a civilian or soldier to slip behind enemy lines.\n",
L"Will be detected if performing suspicious actions, having\nsuspicious gear or being near fresh corpses.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to the enemy.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to a fresh corpse.\n",
L"+%d%s CTH with covert melee weapons\n",
L"+%d%s chance of instakill with covert melee weapons\n",
L"Disguise AP cost lowered by %d%s.\n",
};
STR16 gzIMPMajorTraitsHelpTextsNone[]=
{
L"Нет преимуществ",
+1
View File
@@ -17,6 +17,7 @@ extern STR16 gzIMPMajorTraitsHelpTextsMartialArts[];
extern STR16 gzIMPMajorTraitsHelpTextsSquadleader[];
extern STR16 gzIMPMajorTraitsHelpTextsTechnician[];
extern STR16 gzIMPMajorTraitsHelpTextsDoctor[];
extern STR16 gzIMPMajorTraitsHelpTextsCovertOps[]; // added by Flugente
extern STR16 gzIMPMajorTraitsHelpTextsNone[];
extern STR16 gzIMPMinorTraitsHelpTextsAmbidextrous[];
+12
View File
@@ -59,6 +59,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"Deputy",
L"Technician",
L"Paramedic",
L"Covert Ops", // TODO.Translate
L"None",
L"I.M.P. Major Traits",
@@ -72,6 +73,7 @@ STR16 gzIMPSkillTraitsTextNewMajor[]=
L"Squadleader",
L"Engineer",
L"Doctor",
L"Spy", // TODO.Translate
};
//added another set of skill texts for new minor traits
@@ -242,6 +244,16 @@ STR16 gzIMPMajorTraitsHelpTextsDoctor[]=
L" (max %d these bonuses per sector)",
};
STR16 gzIMPMajorTraitsHelpTextsCovertOps[]= // TODO.Translate
{
L"Can disguise as a civilian or soldier to slip behind enemy lines.\n",
L"Will be detected if performing suspicious actions, having\nsuspicious gear or being near fresh corpses.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to the enemy.\n",
L"Will automatically be detected if disguised as a soldier and\ncloser than %d tiles to a fresh corpse.\n",
L"+%d%s CTH with covert melee weapons\n",
L"+%d%s chance of instakill with covert melee weapons\n",
L"Disguise AP cost lowered by %d%s.\n",
};
STR16 gzIMPMajorTraitsHelpTextsNone[]=
{
L"No bonuses",
+1
View File
@@ -17,6 +17,7 @@ extern STR16 gzIMPMajorTraitsHelpTextsMartialArts[];
extern STR16 gzIMPMajorTraitsHelpTextsSquadleader[];
extern STR16 gzIMPMajorTraitsHelpTextsTechnician[];
extern STR16 gzIMPMajorTraitsHelpTextsDoctor[];
extern STR16 gzIMPMajorTraitsHelpTextsCovertOps[]; // added by Flugente
extern STR16 gzIMPMajorTraitsHelpTextsNone[];
extern STR16 gzIMPMinorTraitsHelpTextsAmbidextrous[];
+2
View File
@@ -7074,6 +7074,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|A|m|m|o |B|e|l|t",
L"|A|m|m|o |V|e|s|t",
L"|D|e|f|u|s|a|l |K|i|t", // TODO.Translate
L"|C|o|v|e|r|t |I|t|e|m",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -7109,6 +7110,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nWith this ammo belt you can\nfeed someone else's MG.",
L"\n \nYou can feed an MG with ammo\nbelts stored in this vest.",
L"\n \nThis item improves your trap disarm chance by ", // TODO.Translate
L"\n \nThis item and everything attached/inside\nit is hidden from curious eyes.",
};
STR16 szUDBAdvStatsTooltipText[]=
+2
View File
@@ -7042,6 +7042,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|A|m|m|o |B|e|l|t",
L"|A|m|m|o |V|e|s|t",
L"|D|e|f|u|s|a|l |K|i|t", // TODO.Translate
L"|C|o|v|e|r|t |I|t|e|m",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -7077,6 +7078,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nWith this ammo belt you can\nfeed someone else's MG.",
L"\n \nYou can feed an MG with ammo\nbelts stored in this vest.",
L"\n \nThis item improves your trap disarm chance by ", // TODO.Translate
L"\n \nThis item and everything attached/inside\nit is hidden from curious eyes.",
};
STR16 szUDBAdvStatsTooltipText[]=
+2
View File
@@ -7079,6 +7079,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]=
L"|A|m|m|o |B|e|l|t",
L"|A|m|m|o |V|e|s|t",
L"|D|e|f|u|s|a|l |K|i|t", // TODO.Translate
L"|C|o|v|e|r|t |I|t|e|m",
};
STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
@@ -7114,6 +7115,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]=
L"\n \nWith this ammo belt you can\nfeed someone else's MG.",
L"\n \nYou can feed an MG with ammo\nbelts stored in this vest.",
L"\n \nThis item improves your trap disarm chance by ", // TODO.Translate
L"\n \nThis item and everything attached/inside\nit is hidden from curious eyes.",
};
STR16 szUDBAdvStatsTooltipText[]=