mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
New feature: interactive actions allow various actions (hacking/reading/drinking/...) from user-defined xml acttions. The exact results can be set in a lua function.
For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=msg&th=23144&goto=346447&#msg_346447 This is fully savegame compatible. GameDir >= r2333 is required. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8278 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -3311,6 +3311,10 @@ void LoadGameAPBPConstants()
|
||||
APBPConstants[AP_APPLYITEM] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_APPLYITEM",50),50);
|
||||
APBPConstants[AP_INVENTORY_ARM] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_INVENTORY_ARM",50),50);
|
||||
APBPConstants[AP_SPOTTER] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_SPOTTER",20),20);
|
||||
APBPConstants[AP_HACK] = DynamicAdjustAPConstants( iniReader.ReadInteger( "APConstants", "AP_HACK", 300 ), 300 );
|
||||
APBPConstants[AP_READFILE] = DynamicAdjustAPConstants( iniReader.ReadInteger( "APConstants", "AP_READFILE", 50 ), 50 );
|
||||
APBPConstants[AP_WATERTAP] = DynamicAdjustAPConstants( iniReader.ReadInteger( "APConstants", "AP_WATERTAP", 20 ), 20 );
|
||||
APBPConstants[AP_SODAMACHINE] = DynamicAdjustAPConstants( iniReader.ReadInteger( "APConstants", "AP_SODAMACHINE", 30 ), 30 );
|
||||
|
||||
APBPConstants[AP_ENTER_VEHICLE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_ENTER_VEHICLE",30),30);
|
||||
APBPConstants[AP_EXIT_VEHICLE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_EXIT_VEHICLE",30),30);
|
||||
|
||||
+9
-9
@@ -15,9 +15,9 @@
|
||||
#ifdef JA2EDITOR
|
||||
|
||||
#ifdef JA2UB
|
||||
CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.8275 (Development Build)" };
|
||||
CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.8278 (Development Build)" };
|
||||
#else
|
||||
CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.8275 (Development Build)" };
|
||||
CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.8278 (Development Build)" };
|
||||
#endif
|
||||
|
||||
// ------------------------------
|
||||
@@ -27,11 +27,11 @@
|
||||
|
||||
//DEBUG BUILD VERSION
|
||||
#ifdef JA2UB
|
||||
CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.8275 (Development Build)" };
|
||||
CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.8278 (Development Build)" };
|
||||
#elif defined (JA113DEMO)
|
||||
CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.8275 (Development Build)" };
|
||||
CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.8278 (Development Build)" };
|
||||
#else
|
||||
CHAR16 zVersionLabel[256] = { L"Debug: v1.13.8275 (Development Build)" };
|
||||
CHAR16 zVersionLabel[256] = { L"Debug: v1.13.8278 (Development Build)" };
|
||||
#endif
|
||||
|
||||
#elif defined CRIPPLED_VERSION
|
||||
@@ -46,16 +46,16 @@
|
||||
|
||||
//RELEASE BUILD VERSION
|
||||
#ifdef JA2UB
|
||||
CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.8275 (Development Build)" };
|
||||
CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.8278 (Development Build)" };
|
||||
#elif defined (JA113DEMO)
|
||||
CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.8275 (Development Build)" };
|
||||
CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.8278 (Development Build)" };
|
||||
#else
|
||||
CHAR16 zVersionLabel[256] = { L"Release v1.13.8275 (Development Build)" };
|
||||
CHAR16 zVersionLabel[256] = { L"Release v1.13.8278 (Development Build)" };
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
CHAR8 czVersionNumber[16] = { "Build 16.07.17" }; //YY.MM.DD
|
||||
CHAR8 czVersionNumber[16] = { "Build 16.07.31" }; //YY.MM.DD
|
||||
CHAR16 zTrackingNumber[16] = { L"Z" };
|
||||
|
||||
// SAVE_GAME_VERSION is defined in header, change it there
|
||||
|
||||
@@ -391,6 +391,10 @@ BOOLEAN LoadExternalGameplayData(STR directoryName)
|
||||
strcat(fileName, STRUCTURECONSTRUCTFILENAME);
|
||||
SGP_THROW_IFFALSE(ReadInStructureConstructStats(fileName),STRUCTURECONSTRUCTFILENAME);
|
||||
|
||||
strcpy( fileName, directoryName );
|
||||
strcat( fileName, INTERACTIVEACTIONSFILENAME );
|
||||
SGP_THROW_IFFALSE( ReadInInteractiveActionsStats( fileName ), INTERACTIVEACTIONSFILENAME );
|
||||
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, MERCHANTSFILENAME);
|
||||
SGP_THROW_IFFALSE(ReadInMerchantStats(fileName),MERCHANTSFILENAME);
|
||||
|
||||
@@ -154,6 +154,10 @@ AP_HANDCUFF,
|
||||
AP_APPLYITEM,
|
||||
AP_INVENTORY_ARM,
|
||||
AP_SPOTTER,
|
||||
AP_HACK,
|
||||
AP_READFILE,
|
||||
AP_WATERTAP,
|
||||
AP_SODAMACHINE,
|
||||
|
||||
AP_ENTER_VEHICLE,
|
||||
AP_EXIT_VEHICLE,
|
||||
|
||||
@@ -857,6 +857,9 @@ static int l_SetModderLUAFact( lua_State *L );
|
||||
static int l_SetScreenMsg( lua_State *L );
|
||||
static int l_GetUsedLanguage( lua_State *L );
|
||||
|
||||
static int l_DoInteractiveActionDefaultResult( lua_State *L );
|
||||
static int l_GiveExp( lua_State *L );
|
||||
|
||||
using namespace std;
|
||||
|
||||
UINT16 idProfil;
|
||||
@@ -1722,6 +1725,9 @@ void IniFunction(lua_State *L, BOOLEAN bQuests )
|
||||
|
||||
lua_register( L, "SetScreenMsg", l_SetScreenMsg );
|
||||
lua_register( L, "GetUsedLanguage", l_GetUsedLanguage );
|
||||
|
||||
lua_register( L, "DoInteractiveActionDefaultResult", l_DoInteractiveActionDefaultResult );
|
||||
lua_register( L, "GiveExp", l_GiveExp );
|
||||
}
|
||||
#ifdef NEWMUSIC
|
||||
BOOLEAN LetLuaMusicControl(UINT8 Init)
|
||||
@@ -2648,6 +2654,24 @@ void LuaHandleSectorLiberation( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, B
|
||||
LuaFunction( _LS.L, "HandleSectorLiberation" ).Param<int>( sSectorX ).Param<int>( sSectorY ).Param<int>( bSectorZ ).Param<bool>( fFirstTime ).Call( 4 );
|
||||
}
|
||||
|
||||
void LuaHandleInteractiveActionResult( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ,
|
||||
INT32 sGridNo, UINT8 bLevel, UINT8 ubId,
|
||||
UINT8 usActionType, INT32 sLuaactionid, INT32 difficulty, UINT16 skill )
|
||||
{
|
||||
const char* filename = "scripts\\Overhead.lua";
|
||||
|
||||
LuaScopeState _LS( true );
|
||||
|
||||
lua_register( _LS.L( ), "CheckFact", l_CheckFact );
|
||||
lua_register( _LS.L( ), "AddVolunteers", l_AddVolunteers );
|
||||
IniFunction( _LS.L( ), TRUE );
|
||||
IniGlobalGameSetting( _LS.L( ) );
|
||||
|
||||
SGP_THROW_IFFALSE( _LS.L.EvalFile( filename ), _BS( "Cannot open file: " ) << filename << _BS::cget );
|
||||
|
||||
LuaFunction( _LS.L, "HandleInteractiveActionResult" ).Param<int>( sSectorX ).Param<int>( sSectorY ).Param<int>( bSectorZ ).Param<int>( sGridNo ).Param<int>( bLevel ).Param<int>( ubId ).Param<int>( usActionType ).Param<int>( sLuaactionid ).Param<int>( difficulty ).Param<int>( skill ).Call( 10 );
|
||||
}
|
||||
|
||||
void LuaRecruitRPCAdditionalHandling( UINT8 usProfile )
|
||||
{
|
||||
const char* filename = "scripts\\strategicmap.lua";
|
||||
@@ -13241,3 +13265,34 @@ static int l_GetUsedLanguage( lua_State *L )
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_DoInteractiveActionDefaultResult( lua_State *L )
|
||||
{
|
||||
if ( lua_gettop( L ) >= 3 )
|
||||
{
|
||||
INT32 sGridNo = lua_tointeger( L, 1 );
|
||||
UINT8 ubID = lua_tointeger( L, 2 );
|
||||
BOOLEAN success = lua_tointeger( L, 3 );
|
||||
|
||||
DoInteractiveActionDefaultResult( sGridNo, ubID, success );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_GiveExp( lua_State *L )
|
||||
{
|
||||
if ( lua_gettop( L ) >= 3 )
|
||||
{
|
||||
UINT8 ubID = lua_tointeger( L, 1 );
|
||||
UINT8 ubStat = lua_tointeger( L, 2 );
|
||||
UINT16 usNumChances = lua_tointeger( L, 3 );
|
||||
|
||||
if ( ubID != NOBODY && ubStat >= FIRST_CHANGEABLE_STAT && ubStat <= LAST_CHANGEABLE_STAT )
|
||||
{
|
||||
StatChange( MercPtrs[ubID], ubStat, usNumChances, FROM_SUCCESS );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -60,6 +60,9 @@ extern BOOLEAN LuaHandleQuestCodeOnSector( INT16 sSectorX, INT16 sSectorY, INT8
|
||||
//extern BOOLEAN LuaHandleQuestCodeOnSectorEntry( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 Init);
|
||||
|
||||
void LuaHandleSectorLiberation( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, BOOLEAN fFirstTime );
|
||||
void LuaHandleInteractiveActionResult( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ,
|
||||
INT32 sGridNo, UINT8 bLevel, UINT8 ubId,
|
||||
UINT8 usActionType, INT32 sLuaactionid, INT32 difficulty, UINT16 skill );
|
||||
void LuaRecruitRPCAdditionalHandling( UINT8 usProfile );
|
||||
void LuaHandleSectorTacticalEntry( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, BOOLEAN fHasEverBeenPlayerControlled );
|
||||
|
||||
|
||||
+6
-1
@@ -2212,7 +2212,12 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
|
||||
}
|
||||
|
||||
// Flugente: add an icon if we are performing a multi-turn action
|
||||
if ( MercPtrs[ pFace->ubSoldierID ]->GetMultiTurnAction() > MTA_NONE )
|
||||
if ( MercPtrs[pFace->ubSoldierID]->GetMultiTurnAction( ) == MTA_HACK )
|
||||
{
|
||||
DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 30 );
|
||||
bNumRightIcons++;
|
||||
}
|
||||
else if ( MercPtrs[ pFace->ubSoldierID ]->GetMultiTurnAction() > MTA_NONE )
|
||||
{
|
||||
DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 14 );
|
||||
bNumRightIcons++;
|
||||
|
||||
@@ -1119,3 +1119,38 @@ BOOLEAN HasFoodInInventory( SOLDIERTYPE *pSoldier, BOOLEAN fCheckFood, BOOLEAN f
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void DrinkFromWaterTap( SOLDIERTYPE* pSoldier )
|
||||
{
|
||||
if ( !pSoldier )
|
||||
return;
|
||||
|
||||
// dont feed our machines
|
||||
if ( pSoldier->ubProfile == ROBOT || IsVehicle( pSoldier ) )
|
||||
return;
|
||||
|
||||
if ( gGameOptions.fFoodSystem )
|
||||
{
|
||||
INT32 watertoadd = max( 0, FoodMoraleMods[FOOD_NORMAL].bThreshold - pSoldier->bDrinkLevel );
|
||||
|
||||
if ( watertoadd > 0 )
|
||||
{
|
||||
AddFoodpoints( pSoldier->bDrinkLevel, watertoadd );
|
||||
}
|
||||
}
|
||||
|
||||
if ( GetWaterQuality( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) == WATER_POISONOUS )
|
||||
HandlePossibleInfection( pSoldier, NULL, INFECTION_TYPE_BADWATER );
|
||||
|
||||
INT32 bpadded = 100 * min( 20, 100 - pSoldier->bBreath );
|
||||
|
||||
DeductPoints( pSoldier, 20, -bpadded );
|
||||
|
||||
// play water sound
|
||||
if ( pSoldier->bTeam == gbPlayerNum && gGameExternalOptions.fFoodEatingSounds )
|
||||
{
|
||||
PlayJA2SampleFromFile( "Sounds\\watertap.wav", RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
||||
}
|
||||
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szInteractiveActionText[8], pSoldier->GetName( ) );
|
||||
}
|
||||
@@ -107,4 +107,6 @@ void SoldierAutoFillCanteens(SOLDIERTYPE *pSoldier);
|
||||
|
||||
BOOLEAN HasFoodInInventory( SOLDIERTYPE *pSoldier, BOOLEAN fCheckFood, BOOLEAN fCheckDrink );
|
||||
|
||||
void DrinkFromWaterTap( SOLDIERTYPE *pSoldier );
|
||||
|
||||
#endif
|
||||
|
||||
+241
-6
@@ -72,6 +72,10 @@
|
||||
#include <fstream> // added by Flugente
|
||||
#include "DisplayCover.h" // added by Flugente
|
||||
#include "Queen Command.h" // added by Flugente for FindUnderGroundSector(...)
|
||||
#include "LuaInitNPCs.h" // added by Flugente
|
||||
#include "finances.h" // added by Flugente
|
||||
#include "LaptopSave.h" // added by Flugente
|
||||
#include "Game Clock.h" // added by Flugente
|
||||
#include <vfs/Core/vfs_file_raii.h> // added by Flugente for vfs-stuff
|
||||
#endif
|
||||
|
||||
@@ -325,7 +329,90 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
|
||||
return( ITEM_HANDLE_REFUSAL );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INT32 usMapPos;
|
||||
GetMouseMapPos( &usMapPos );
|
||||
|
||||
// Flugente: interactive actions
|
||||
if ( Item[usHandItem].ubCursor == INVALIDCURS || usHandItem == NONE )
|
||||
{
|
||||
UINT16 structindex;
|
||||
UINT16 possibleaction = InteractiveActionPossibleAtGridNo( usMapPos, pSoldier->pathing.bLevel, structindex );
|
||||
if ( possibleaction )//&& pSoldier->GetInteractiveActionSkill( usMapPos, pSoldier->pathing.bLevel, possibleaction ) )
|
||||
{
|
||||
// ATE: AI CANNOT GO THROUGH HERE!
|
||||
BOOLEAN fHadToUseCursorPos = FALSE;
|
||||
|
||||
// See if we can get there to stab
|
||||
sActionGridNo = FindAdjacentGridEx( pSoldier, usMapPos, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
|
||||
if ( sActionGridNo == NOWHERE )
|
||||
{
|
||||
// Try another location...
|
||||
sActionGridNo = FindAdjacentGridEx( pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
|
||||
|
||||
if ( sActionGridNo == NOWHERE )
|
||||
{
|
||||
return(ITEM_HANDLE_CANNOT_GETTO_LOCATION);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate AP costs...
|
||||
sAPCost = 0;//GetAPsToHandcuff( pSoldier, sActionGridNo );
|
||||
sAPCost += PlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, FALSE, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
|
||||
|
||||
if ( EnoughPoints( pSoldier, sAPCost, 0, fFromUI ) )
|
||||
{
|
||||
// OK, set UI
|
||||
SetUIBusy( pSoldier->ubID );
|
||||
|
||||
// CHECK IF WE ARE AT THIS GRIDNO NOW
|
||||
if ( pSoldier->sGridNo != sActionGridNo )
|
||||
{
|
||||
// SEND PENDING ACTION
|
||||
pSoldier->aiData.ubPendingAction = MERC_INTERACTIVEACTION;
|
||||
|
||||
if ( fHadToUseCursorPos )
|
||||
{
|
||||
pSoldier->aiData.sPendingActionData2 = usMapPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pTargetSoldier != NULL )
|
||||
{
|
||||
pSoldier->aiData.sPendingActionData2 = pTargetSoldier->sGridNo;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSoldier->aiData.sPendingActionData2 = sGridNo;
|
||||
}
|
||||
}
|
||||
|
||||
pSoldier->aiData.bPendingActionData3 = (INT8)(possibleaction);
|
||||
pSoldier->aiData.ubPendingActionAnimCount = 0;
|
||||
|
||||
// WALK UP TO DEST FIRST
|
||||
pSoldier->EVENT_InternalGetNewSoldierPath( sActionGridNo, pSoldier->usUIMovementMode, FALSE, TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
pSoldier->EVENT_SoldierInteractiveAction( sAdjustedGridNo, possibleaction );
|
||||
|
||||
UnSetUIBusy( pSoldier->ubID );
|
||||
}
|
||||
|
||||
if ( fFromUI )
|
||||
{
|
||||
guiPendingOverrideEvent = A_CHANGE_TO_MOVE;
|
||||
}
|
||||
|
||||
return(ITEM_HANDLE_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(ITEM_HANDLE_NOAPS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check HAND ITEM
|
||||
@@ -1236,11 +1323,8 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
|
||||
if ( gGameExternalOptions.fAllowPrisonerSystem && HasItemFlag( usHandItem, HANDCUFFS ) && pTargetSoldier && pTargetSoldier->CanBeCaptured( ) )
|
||||
{
|
||||
// ATE: AI CANNOT GO THROUGH HERE!
|
||||
INT32 usMapPos;
|
||||
BOOLEAN fHadToUseCursorPos = FALSE;
|
||||
|
||||
GetMouseMapPos( &usMapPos );
|
||||
|
||||
// See if we can get there to stab
|
||||
sActionGridNo = FindAdjacentGridEx( pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
|
||||
if ( sActionGridNo == -1 )
|
||||
@@ -1319,11 +1403,8 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
|
||||
if ( ItemCanBeAppliedToOthers( usHandItem ) )
|
||||
{
|
||||
// ATE: AI CANNOT GO THROUGH HERE!
|
||||
INT32 usMapPos;
|
||||
BOOLEAN fHadToUseCursorPos = FALSE;
|
||||
|
||||
GetMouseMapPos( &usMapPos );
|
||||
|
||||
// See if we can get there to stab
|
||||
sActionGridNo = FindAdjacentGridEx( pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
|
||||
if ( sActionGridNo == -1 )
|
||||
@@ -8696,3 +8777,157 @@ void HandleTakeNewBombFromInventory(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj)
|
||||
pSoldier->TakeNewBombFromInventory(pObj->usItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: interactive actions
|
||||
void DoInteractiveAction( INT32 sGridNo, SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
// we need a valid soldier and a valid object
|
||||
if ( !pSoldier )
|
||||
return;
|
||||
|
||||
// needs to be a valid location
|
||||
if ( TileIsOutOfBounds( sGridNo ) )
|
||||
return;
|
||||
|
||||
UINT16 structindex;
|
||||
UINT16 possibleaction = InteractiveActionPossibleAtGridNo( sGridNo, pSoldier->pathing.bLevel, structindex );
|
||||
|
||||
UINT16 skill = pSoldier->GetInteractiveActionSkill( sGridNo, pSoldier->pathing.bLevel, possibleaction );
|
||||
|
||||
INT32 difficulty = gInteractiveStructure[structindex].difficulty;
|
||||
INT32 luaactionid = gInteractiveStructure[structindex].luaactionid;
|
||||
|
||||
// play sounds
|
||||
switch ( possibleaction )
|
||||
{
|
||||
case INTERACTIVE_STRUCTURE_HACKABLE:
|
||||
PlayJA2SampleFromFile( "Sounds\\keyboard_typing.wav", RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
||||
break;
|
||||
|
||||
case INTERACTIVE_STRUCTURE_READFILE:
|
||||
PlayJA2SampleFromFile( "Sounds\\book_pageturn1.wav", RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( possibleaction == INTERACTIVE_STRUCTURE_HACKABLE )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szInteractiveActionText[0], pSoldier->GetName( ) );
|
||||
|
||||
// hacking is a multiturn-action - we only start the action here, the result is handled elsewhere
|
||||
pSoldier->StartMultiTurnAction( MTA_HACK, sGridNo );
|
||||
}
|
||||
// call lua with the action id - perhaps we might do something special here
|
||||
else if ( luaactionid >= 0 )
|
||||
{
|
||||
LuaHandleInteractiveActionResult( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, sGridNo, pSoldier->pathing.bLevel, pSoldier->ubID, possibleaction, luaactionid, difficulty, skill );
|
||||
}
|
||||
else
|
||||
{
|
||||
DoInteractiveActionDefaultResult( sGridNo, pSoldier->ubID, (skill >= difficulty) );
|
||||
}
|
||||
}
|
||||
|
||||
// handle the default result of an interactive action
|
||||
// This is called either if no lua action id is set, or by lua if this should happen as a supplement to whatever lua does
|
||||
void DoInteractiveActionDefaultResult( INT32 sGridNo, UINT8 ubID, BOOLEAN aSuccess )
|
||||
{
|
||||
SOLDIERTYPE* pSoldier = NULL;
|
||||
if ( ubID != NOBODY )
|
||||
pSoldier = MercPtrs[ubID];
|
||||
|
||||
// we need a valid soldier and a valid object
|
||||
if ( !pSoldier )
|
||||
return;
|
||||
|
||||
// needs to be a valid location
|
||||
if ( TileIsOutOfBounds( sGridNo ) )
|
||||
return;
|
||||
|
||||
UINT16 structindex;
|
||||
UINT16 possibleaction = InteractiveActionPossibleAtGridNo( sGridNo, pSoldier->pathing.bLevel, structindex );
|
||||
|
||||
switch ( possibleaction )
|
||||
{
|
||||
case INTERACTIVE_STRUCTURE_HACKABLE:
|
||||
{
|
||||
if ( aSuccess )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szInteractiveActionText[1], pSoldier->GetName( ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szInteractiveActionText[2], pSoldier->GetName( ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case INTERACTIVE_STRUCTURE_READFILE:
|
||||
{
|
||||
if ( aSuccess )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szInteractiveActionText[3], pSoldier->GetName( ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szInteractiveActionText[4], pSoldier->GetName( ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case INTERACTIVE_STRUCTURE_WATERTAP:
|
||||
{
|
||||
if ( aSuccess )
|
||||
{
|
||||
DrinkFromWaterTap( pSoldier );
|
||||
}
|
||||
else
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szInteractiveActionText[5], pSoldier->GetName( ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case INTERACTIVE_STRUCTURE_SODAMACHINE:
|
||||
{
|
||||
static UINT16 usSodaIndex = 1741;
|
||||
|
||||
// we still have to determine whether a soda item exists, and whether we can pay for it
|
||||
if ( aSuccess )
|
||||
{
|
||||
aSuccess = FALSE;
|
||||
|
||||
// determine soda item, only if this exists can we proceed to sell one
|
||||
if ( HasItemFlag( usSodaIndex, SODA ) || GetFirstItemWithFlag( &usSodaIndex, SODA ) )
|
||||
{
|
||||
if ( LaptopSaveInfo.iCurrentBalance >= Item[usSodaIndex].usPrice )
|
||||
{
|
||||
aSuccess = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( aSuccess )
|
||||
{
|
||||
if ( CreateItem( usSodaIndex, 100, &gTempObject ) && AutoPlaceObjectAnywhere( pSoldier, &gTempObject, TRUE ) )
|
||||
{
|
||||
AddTransactionToPlayersBook( TRANSFER_FUNDS_TO_MERC, pSoldier->ubProfile, GetWorldTotalMin( ), Item[usSodaIndex].usPrice );
|
||||
|
||||
PlayJA2SampleFromFile( "Sounds\\soda_machine.wav", RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
||||
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szInteractiveActionText[6], pSoldier->GetName( ), Item[usSodaIndex].szItemName );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szInteractiveActionText[7], pSoldier->GetName( ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +111,52 @@ typedef struct {
|
||||
|
||||
extern STRUCTURE_CONSTRUCT gStructureConstruct[STRUCTURE_CONSTRUCT_MAX];
|
||||
|
||||
// Flugente: we can define what structures we can interact with (example: we can hack computers or retrieve information from a file cabinet)
|
||||
typedef enum
|
||||
{
|
||||
INTERACTIVE_STRUCTURE_NO_ACTION,
|
||||
|
||||
INTERACTIVE_STRUCTURE_HACKABLE,
|
||||
INTERACTIVE_STRUCTURE_READFILE,
|
||||
INTERACTIVE_STRUCTURE_WATERTAP,
|
||||
INTERACTIVE_STRUCTURE_SODAMACHINE,
|
||||
|
||||
INTERACTIVE_STRUCTURE_TYPE_MAX,
|
||||
} INTERACTIVE_STRUCTURE_TYPE;
|
||||
|
||||
typedef struct INTERACTIVE_STRUCTURE {
|
||||
void reset()
|
||||
{
|
||||
sector = -1;
|
||||
sectorlevel = -1;
|
||||
tileindexvector.clear( );
|
||||
gridnovector.clear( );
|
||||
sLevel = -1;
|
||||
sActionType = INTERACTIVE_STRUCTURE_NO_ACTION;
|
||||
difficulty = 0;
|
||||
luaactionid = -1;
|
||||
}
|
||||
|
||||
INT16 sector;
|
||||
INT8 sectorlevel; // whether this is on the surface (0) or below (1-3)
|
||||
char szTileSetName[20]; // name of the tileset
|
||||
std::vector<UINT16> tileindexvector; // possible indizes in tileset
|
||||
|
||||
// We can either specify a specific location, or simply leave this empty
|
||||
// in that case, this action will apply to all locations fitting the above criteria, but a specific location definition always takes preference
|
||||
std::vector<INT32> gridnovector; // possible gridnos
|
||||
INT8 sLevel;
|
||||
|
||||
UINT16 sActionType; // one of INTERACTIVE_STRUCTURE_TYPE
|
||||
INT32 difficulty;
|
||||
INT32 luaactionid; // call lua with this ID after performing the usual action - perhaps something special has to happen
|
||||
} INTERACTIVE_STRUCTURE;
|
||||
|
||||
#define INTERACTIVE_STRUCTURE_MAX 200
|
||||
|
||||
extern INTERACTIVE_STRUCTURE gInteractiveStructure[INTERACTIVE_STRUCTURE_MAX];
|
||||
extern UINT32 gMaxInteractiveStructureRead;
|
||||
|
||||
class SOLDIERTYPE;
|
||||
INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHandItem, BOOLEAN fFromUI );
|
||||
void SoldierPickupItem( SOLDIERTYPE *pSoldier, INT32 iItemIndex, INT32 sGridNo, INT8 bZLevel );
|
||||
@@ -253,4 +299,8 @@ INT32 GetFirstObjectInSectorPosition( UINT16 ausItem );
|
||||
|
||||
extern ITEM_POOL *gpItemPool;//dnl ch26 210909
|
||||
|
||||
// Flugente: interactive actions
|
||||
void DoInteractiveAction( INT32 sGridNo, SOLDIERTYPE *pSoldier );
|
||||
void DoInteractiveActionDefaultResult( INT32 sGridNo, UINT8 ubID, BOOLEAN aSuccess );
|
||||
|
||||
#endif
|
||||
+37
-2
@@ -4258,6 +4258,26 @@ INT8 DrawUIMovementPath( SOLDIERTYPE *pSoldier, INT32 usMapPos, UINT32 uiFlags )
|
||||
gsUIHandleShowMoveGridLocation = sActionGridNo;
|
||||
}
|
||||
}
|
||||
else if ( uiFlags == MOVEUI_TARGET_INTERACTIVEACTION )
|
||||
{
|
||||
sActionGridNo = FindAdjacentGridEx( pSoldier, usMapPos, &ubDirection, NULL, FALSE, TRUE );
|
||||
if ( sActionGridNo == -1 )
|
||||
{
|
||||
sActionGridNo = usMapPos;
|
||||
}
|
||||
|
||||
UINT16 structindex;
|
||||
UINT16 possibleaction = InteractiveActionPossibleAtGridNo( usMapPos, pSoldier->pathing.bLevel, structindex );
|
||||
|
||||
sAPCost = GetAPsForInteractiveAction( pSoldier, possibleaction );
|
||||
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
|
||||
|
||||
if ( sActionGridNo != pSoldier->sGridNo )
|
||||
{
|
||||
gfUIHandleShowMoveGrid = TRUE;
|
||||
gsUIHandleShowMoveGridLocation = sActionGridNo;
|
||||
}
|
||||
}
|
||||
else if ( uiFlags == MOVEUI_TARGET_MERCS )
|
||||
{
|
||||
INT32 sGotLocation = NOWHERE;
|
||||
@@ -4600,6 +4620,23 @@ BOOLEAN UIMouseOnValidAttackLocation( SOLDIERTYPE *pSoldier )
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
if ( ubItemCursor == INTERACTIVEACTIONCURS )
|
||||
{
|
||||
if ( gfUIFullTargetFound )
|
||||
{
|
||||
usMapPos = MercPtrs[gusUIFullTargetID]->sGridNo;
|
||||
}
|
||||
|
||||
UINT16 structindex;
|
||||
UINT16 possibleaction = InteractiveActionPossibleAtGridNo( usMapPos, pSoldier->pathing.bLevel, structindex );
|
||||
if ( possibleaction )//&& pSoldier->GetInteractiveActionSkill( usMapPos, pSoldier->pathing.bLevel, possibleaction ) )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( ubItemCursor == HANDCUFFCURS )
|
||||
{
|
||||
if ( HasItemFlag( (&(pSoldier->inv[HANDPOS]))->usItem, HANDCUFFS ) )
|
||||
@@ -6436,7 +6473,6 @@ INT8 UIHandleInteractiveTilesAndItemsOnTerrain( SOLDIERTYPE *pSoldier, INT32 usM
|
||||
BOOLEAN fPoolContainsHiddenItems = FALSE;
|
||||
SOLDIERTYPE *pTSoldier;
|
||||
|
||||
|
||||
if ( gfResetUIItemCursorOptimization )
|
||||
{
|
||||
gfResetUIItemCursorOptimization = FALSE;
|
||||
@@ -6677,7 +6713,6 @@ INT8 UIHandleInteractiveTilesAndItemsOnTerrain( SOLDIERTYPE *pSoldier, INT32 usM
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( pIntTile == NULL )
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#define MOVEUI_TARGET_FORTIFICATION 13
|
||||
#define MOVEUI_TARGET_HANDCUFF 14
|
||||
#define MOVEUI_TARGET_APPLYITEM 15
|
||||
#define MOVEUI_TARGET_INTERACTIVEACTION 16
|
||||
|
||||
#define MOVEUI_RETURN_ON_TARGET_MERC 1
|
||||
|
||||
|
||||
@@ -218,6 +218,18 @@ UICursor gUICursors[ NUM_UI_CURSORS ] =
|
||||
APPLYITEM_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_APPLYITEM, 0,
|
||||
APPLYITEM_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_APPLYITEM_RED, 0,
|
||||
|
||||
HACK_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_HACK, 0,
|
||||
HACK_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_HACK_RED, 0,
|
||||
|
||||
READFILE_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_READFILE, 0,
|
||||
READFILE_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_READFILE_RED, 0,
|
||||
|
||||
WATERTAP_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_WATERTAP, 0,
|
||||
WATERTAP_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_WATERTAP_RED, 0,
|
||||
|
||||
SODAMACHINE_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_SODAMACHINE, 0,
|
||||
SODAMACHINE_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_SODAMACHINE_RED, 0,
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -195,6 +195,18 @@ typedef enum
|
||||
APPLYITEM_GREY_UICURSOR,
|
||||
APPLYITEM_RED_UICURSOR,
|
||||
|
||||
HACK_GREY_UICURSOR,
|
||||
HACK_RED_UICURSOR,
|
||||
|
||||
READFILE_GREY_UICURSOR,
|
||||
READFILE_RED_UICURSOR,
|
||||
|
||||
WATERTAP_GREY_UICURSOR,
|
||||
WATERTAP_RED_UICURSOR,
|
||||
|
||||
SODAMACHINE_GREY_UICURSOR,
|
||||
SODAMACHINE_RED_UICURSOR,
|
||||
|
||||
NUM_UI_CURSORS
|
||||
|
||||
} UICursorDefines;
|
||||
|
||||
@@ -197,7 +197,8 @@ enum {
|
||||
BG_DISLIKEBG, // dislike any other background that has the negative of this value set
|
||||
BG_SMOKERTYPE, // 0: doesnt care about smoking 1: will consume cigarettes, dislikes non-smokers 2: will refuse to smoke, dislikes smokers
|
||||
BG_CROUCHEDDEFENSE, // lowers enemy cth if they fire at us while we are crouched against cover in the direction the shots come from
|
||||
BG_FORTIFY_ASSIGNMENT, // modifies effectivity of 'FORTIFICATION' assignemnt
|
||||
BG_FORTIFY_ASSIGNMENT, // modifies effectivity of 'FORTIFICATION' assignment
|
||||
BG_HACKERSKILL, // hacking skill from 0 to 100, > 0 means hacking is possible
|
||||
|
||||
BG_MAX,
|
||||
};
|
||||
|
||||
@@ -176,6 +176,7 @@ typedef enum ATTACHMENT_SLOT{
|
||||
#define FORTICURS 24
|
||||
#define HANDCUFFCURS 25
|
||||
#define APPLYITEMCURS 26
|
||||
#define INTERACTIVEACTIONCURS 27
|
||||
|
||||
#define CAMERARANGE 10
|
||||
|
||||
@@ -763,7 +764,7 @@ extern OBJECTTYPE gTempObject;
|
||||
#define TRIPWIREROLL 0x01000000 //16777216 // this item is a tripwire roll
|
||||
#define RADIO_SET 0x02000000 //33554432 // item can be used to radio militia/squads in other sectors
|
||||
#define SIGNAL_SHELL 0x04000000 //67108864 // this is a signal shell that precedes artillery barrages
|
||||
//#define POWER_PACK 0x08000000 //134217728 // item continously powers an item it is attached to
|
||||
#define SODA 0x08000000 //134217728 // item is a can of soda, sold in vending machines
|
||||
|
||||
#define ROOF_COLLAPSE_ITEM 0x10000000 //268435456 // this item is required in the collapsing of roof tiles. It is used internally and should never be seen by the player
|
||||
#define DISEASEPROTECTION_1 0x20000000 //536870912 // this item protects us from getting diseases by human contact if kept in inventory
|
||||
@@ -1138,6 +1139,9 @@ typedef struct
|
||||
UINT8 DisarmModifier;
|
||||
INT8 RepairModifier;
|
||||
|
||||
// Flugente: a modifier to hacking
|
||||
UINT8 usHackingModifier;
|
||||
|
||||
// Flugente: advanced repair/dirt system
|
||||
UINT8 usDamageChance; // chance that damage to the status will also damage the repair threshold
|
||||
FLOAT dirtIncreaseFactor; // one shot causes this much dirt on a gun
|
||||
|
||||
@@ -1382,6 +1382,10 @@ BOOLEAN ExecuteOverhead( )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: we are doing something here - stop multi-turn-action
|
||||
pSoldier->CancelMultiTurnAction( FALSE );
|
||||
|
||||
if ( pSoldier->aiData.ubPendingAction == MERC_PICKUPITEM )
|
||||
{
|
||||
sGridNo = pSoldier->aiData.sPendingActionData2;
|
||||
@@ -1538,6 +1542,11 @@ BOOLEAN ExecuteOverhead( )
|
||||
pSoldier->EVENT_SoldierBeginGiveItem( );
|
||||
pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION;
|
||||
}
|
||||
else if ( pSoldier->aiData.ubPendingAction == MERC_INTERACTIVEACTION )
|
||||
{
|
||||
pSoldier->EVENT_SoldierInteractiveAction( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 );
|
||||
pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION;
|
||||
}
|
||||
|
||||
if ( fNoAPsForPendingAction )
|
||||
{
|
||||
@@ -1547,7 +1556,6 @@ BOOLEAN ExecuteOverhead( )
|
||||
pSoldier->usPendingAnimation = NO_PENDING_ANIMATION;
|
||||
pSoldier->ubPendingDirection = NO_PENDING_DIRECTION;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -4000,6 +4000,9 @@ INT16 GetAPsForMultiTurnAction( SOLDIERTYPE *pSoldier, UINT8 usActionType )
|
||||
case MTA_REMOVE_FORTIFY:
|
||||
sAPCost += APBPConstants[AP_REMOVE_FORTIFICATION];
|
||||
break;
|
||||
case MTA_HACK:
|
||||
sAPCost += APBPConstants[AP_HACK];
|
||||
break;
|
||||
}
|
||||
|
||||
if ( usActionType == MTA_FORTIFY || usActionType == MTA_REMOVE_FORTIFY )
|
||||
@@ -4010,6 +4013,32 @@ INT16 GetAPsForMultiTurnAction( SOLDIERTYPE *pSoldier, UINT8 usActionType )
|
||||
return sAPCost;
|
||||
}
|
||||
|
||||
INT16 GetAPsForInteractiveAction( SOLDIERTYPE *pSoldier, UINT8 usActionType )
|
||||
{
|
||||
INT16 sAPCost = 0;
|
||||
|
||||
switch ( usActionType )
|
||||
{
|
||||
case INTERACTIVE_STRUCTURE_HACKABLE:
|
||||
sAPCost = GetAPsForMultiTurnAction( pSoldier, MTA_HACK );
|
||||
break;
|
||||
case INTERACTIVE_STRUCTURE_READFILE:
|
||||
sAPCost += APBPConstants[AP_READFILE];
|
||||
break;
|
||||
case INTERACTIVE_STRUCTURE_WATERTAP:
|
||||
sAPCost += APBPConstants[AP_WATERTAP];
|
||||
break;
|
||||
case INTERACTIVE_STRUCTURE_SODAMACHINE:
|
||||
sAPCost += APBPConstants[AP_SODAMACHINE];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return sAPCost;
|
||||
}
|
||||
|
||||
INT16 GetAPsToJumpOver( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
// -25% APs needed to for MA traits
|
||||
|
||||
@@ -356,6 +356,8 @@ INT16 GetAPsToHandcuff( SOLDIERTYPE *pSoldier, INT32 usMapPos ); // added by Flu
|
||||
INT16 GetAPsToApplyItem( SOLDIERTYPE *pSoldier, INT32 usMapPos ); // added by Flugente
|
||||
INT16 GetAPsForMultiTurnAction( SOLDIERTYPE *pSoldier, UINT8 usActionType ); // added by Flugente
|
||||
|
||||
INT16 GetAPsForInteractiveAction( SOLDIERTYPE *pSoldier, UINT8 usActionType ); // added by Flugente
|
||||
|
||||
INT16 GetAPsToJumpOver( SOLDIERTYPE *pSoldier );
|
||||
|
||||
void GetAPChargeForShootOrStabWRTGunRaises( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurningCost, BOOLEAN *pfChargeTurning, BOOLEAN *pfChargeRaise, INT16 bAimTime );
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
#include "Cheats.h" // added by Flugente
|
||||
#include "MilitiaIndividual.h" // added by Flugente
|
||||
#include "Arms Dealer Init.h" // added by Flugente for armsDealerInfo[]
|
||||
#include "LuaInitNPCs.h" // added by Flugente
|
||||
#endif
|
||||
|
||||
#include "ub_config.h"
|
||||
@@ -16262,12 +16263,13 @@ BOOLEAN SOLDIERTYPE::UpdateMultiTurnAction( )
|
||||
{
|
||||
case MTA_FORTIFY:
|
||||
case MTA_REMOVE_FORTIFY:
|
||||
// building on a roof is forbidden! stop this!
|
||||
|
||||
/*// building on a roof is forbidden! stop this!
|
||||
if ( this->pathing.bLevel != 0 )
|
||||
{
|
||||
CancelMultiTurnAction( FALSE );
|
||||
return FALSE;
|
||||
}
|
||||
}*/
|
||||
|
||||
// we have to be crouched, get out of here, set us to be crouched first
|
||||
if ( gAnimControl[this->usAnimState].ubEndHeight != ANIM_CROUCH )
|
||||
@@ -16275,6 +16277,10 @@ BOOLEAN SOLDIERTYPE::UpdateMultiTurnAction( )
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case MTA_HACK:
|
||||
break;
|
||||
|
||||
default: // default: exit
|
||||
{
|
||||
CancelMultiTurnAction( FALSE );
|
||||
@@ -16289,12 +16295,17 @@ BOOLEAN SOLDIERTYPE::UpdateMultiTurnAction( )
|
||||
// determine the gridno before us and the item we have in our main hand, this is enough for the current actions
|
||||
OBJECTTYPE* pObj = &(this->inv[HANDPOS]);
|
||||
|
||||
// error if the gridno we started working on is not the gridno we are currently looking at
|
||||
// error if object is missing
|
||||
if ( usMultiTurnAction == MTA_FORTIFY || usMultiTurnAction == MTA_REMOVE_FORTIFY )
|
||||
{
|
||||
if ( !pObj || !(pObj->exists( )) )
|
||||
fActionStillValid = FALSE;
|
||||
else if ( this->sMTActionGridNo != NewGridNo( this->sGridNo, DirectionInc( this->ubDirection ) ) )
|
||||
}
|
||||
|
||||
// error if the gridno we started working on is not the gridno we are currently looking at
|
||||
if ( usMultiTurnAction == MTA_FORTIFY || usMultiTurnAction == MTA_REMOVE_FORTIFY )//|| usMultiTurnAction == MTA_HACK )
|
||||
{
|
||||
if ( this->sMTActionGridNo != NewGridNo( this->sGridNo, DirectionInc( this->ubDirection ) ) )
|
||||
fActionStillValid = FALSE;
|
||||
}
|
||||
|
||||
@@ -16329,6 +16340,18 @@ BOOLEAN SOLDIERTYPE::UpdateMultiTurnAction( )
|
||||
fActionStillValid = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case MTA_HACK:
|
||||
{
|
||||
entireapcost = GetAPsForMultiTurnAction( this, MTA_HACK );
|
||||
entirebpcost = 0; // hacking isn't exactly hard to do physically :-)
|
||||
|
||||
UINT16 structindex;
|
||||
if ( !this->GetInteractiveActionSkill( this->sMTActionGridNo, this->pathing.bLevel, INTERACTIVE_STRUCTURE_HACKABLE ) ||
|
||||
!InteractiveActionPossibleAtGridNo( this->sMTActionGridNo, this->pathing.bLevel, structindex ) == INTERACTIVE_STRUCTURE_HACKABLE )
|
||||
fActionStillValid = FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !fActionStillValid )
|
||||
@@ -16359,6 +16382,14 @@ BOOLEAN SOLDIERTYPE::UpdateMultiTurnAction( )
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MTA_HACK:
|
||||
{
|
||||
// if we are not in turnbased and no enemies are around, we reduce the number of necessary action points to 0. No need to keep waiting if there's nobody around anyway
|
||||
if ( !(gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT) )
|
||||
bOverTurnAPS = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// if we can afford it, do it now
|
||||
@@ -16388,6 +16419,31 @@ BOOLEAN SOLDIERTYPE::UpdateMultiTurnAction( )
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MTA_HACK:
|
||||
{
|
||||
UINT16 structindex;
|
||||
UINT16 possibleaction = InteractiveActionPossibleAtGridNo( this->sMTActionGridNo, this->pathing.bLevel, structindex );
|
||||
UINT16 skill = this->GetInteractiveActionSkill( sGridNo, this->pathing.bLevel, possibleaction );
|
||||
|
||||
INT32 difficulty = gInteractiveStructure[structindex].difficulty;
|
||||
INT32 luaactionid = gInteractiveStructure[structindex].luaactionid;
|
||||
|
||||
BOOLEAN success = (skill >= difficulty);
|
||||
if ( possibleaction != INTERACTIVE_STRUCTURE_HACKABLE )
|
||||
success = FALSE;
|
||||
|
||||
// call lua with the action id - perhaps we might do something special here
|
||||
if ( luaactionid >= 0 )
|
||||
{
|
||||
LuaHandleInteractiveActionResult( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, sGridNo, this->pathing.bLevel, this->ubID, possibleaction, luaactionid, difficulty, skill );
|
||||
}
|
||||
else
|
||||
{
|
||||
DoInteractiveActionDefaultResult( sGridNo, this->ubID, (skill > difficulty) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ( entireapcost > 0 )
|
||||
@@ -19174,6 +19230,92 @@ UINT8 SOLDIERTYPE::GetWaterSnakeDefenseChance()
|
||||
return (UINT8)(val);
|
||||
}
|
||||
|
||||
// Flugente: interactive actions
|
||||
UINT16 SOLDIERTYPE::GetInteractiveActionSkill( INT32 sGridNo, UINT8 usLevel, UINT16 usType )
|
||||
{
|
||||
switch ( usType )
|
||||
{
|
||||
case INTERACTIVE_STRUCTURE_HACKABLE:
|
||||
{
|
||||
if ( this->ubProfile == ROBOT || IsVehicle( this ) )
|
||||
return 0;
|
||||
|
||||
UINT16 skill = this->GetBackgroundValue( BG_HACKERSKILL );
|
||||
|
||||
// without the background property, we cannot hack at all
|
||||
if ( !skill )
|
||||
return 0;
|
||||
|
||||
FLOAT bestmodifier = 1.0f;
|
||||
|
||||
UINT8 bestequipmentbonus = 0;
|
||||
|
||||
OBJECTTYPE* pObj = NULL;
|
||||
|
||||
INT8 invsize = (INT8)inv.size( ); // remember inventorysize, so we don't call size() repeatedly
|
||||
|
||||
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop ) // ... for all items in our inventory ...
|
||||
{
|
||||
// ... if Item exists and is canteen (that can have drink points) ...
|
||||
if ( inv[bLoop].exists( ) == true && Item[inv[bLoop].usItem].usHackingModifier )
|
||||
{
|
||||
OBJECTTYPE * pObj = &(this->inv[bLoop]); // ... get pointer for this item ...
|
||||
|
||||
if ( pObj != NULL ) // ... if pointer is not obviously useless ...
|
||||
{
|
||||
for ( INT16 i = 0; i < pObj->ubNumberOfObjects; ++i )
|
||||
{
|
||||
FLOAT modifier = 1.0f + (Item[inv[bLoop].usItem].usHackingModifier * (*pObj)[i]->data.objectStatus) / 10000.0f;
|
||||
|
||||
if ( modifier > bestmodifier )
|
||||
bestmodifier = modifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (UINT16)(skill * bestmodifier);
|
||||
}
|
||||
break;
|
||||
|
||||
case INTERACTIVE_STRUCTURE_READFILE:
|
||||
{
|
||||
if ( this->ubProfile == ROBOT || IsVehicle( this ) )
|
||||
return 0;
|
||||
|
||||
// reading is governed by wisdom
|
||||
return this->stats.bWisdom;
|
||||
}
|
||||
break;
|
||||
|
||||
case INTERACTIVE_STRUCTURE_WATERTAP:
|
||||
{
|
||||
if ( this->ubProfile == ROBOT || IsVehicle( this ) )
|
||||
return 0;
|
||||
|
||||
// we are pros at drinking water
|
||||
return 100;
|
||||
}
|
||||
break;
|
||||
|
||||
case INTERACTIVE_STRUCTURE_SODAMACHINE:
|
||||
{
|
||||
if ( this->ubProfile == ROBOT || IsVehicle( this ) )
|
||||
return 0;
|
||||
|
||||
// we are pros at buying from a vending machine
|
||||
return 100;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
INT8 bBandaged; //,savedOurTurn;
|
||||
@@ -20275,6 +20417,11 @@ void SOLDIERTYPE::EVENT_SoldierApplyItemToPerson( INT32 sGridNo, UINT8 ubDirecti
|
||||
}
|
||||
}
|
||||
|
||||
void SOLDIERTYPE::EVENT_SoldierInteractiveAction( INT32 sGridNo, UINT16 usActionType )
|
||||
{
|
||||
DoInteractiveAction( sGridNo, this );
|
||||
}
|
||||
|
||||
void SOLDIERTYPE::EVENT_SoldierBeginReloadRobot( INT32 sGridNo, UINT8 ubDirection, UINT8 ubMercSlot )
|
||||
{
|
||||
UINT8 ubPerson;
|
||||
|
||||
@@ -231,6 +231,7 @@ enum
|
||||
MERC_BUILD_FORTIFICATION,
|
||||
MERC_HANDCUFF_PERSON,
|
||||
MERC_APPLYITEM,
|
||||
MERC_INTERACTIVEACTION,
|
||||
};
|
||||
|
||||
// ENUMERATIONS FOR THROW ACTIONS
|
||||
@@ -565,6 +566,7 @@ enum
|
||||
MTA_NONE = 0,
|
||||
MTA_FORTIFY,
|
||||
MTA_REMOVE_FORTIFY,
|
||||
MTA_HACK,
|
||||
NUM_MTA,
|
||||
};
|
||||
|
||||
@@ -1626,6 +1628,7 @@ public:
|
||||
void EVENT_SoldierBuildStructure( INT32 sGridNo, UINT8 ubDirection ); // added by Flugente
|
||||
void EVENT_SoldierHandcuffPerson( INT32 sGridNo, UINT8 ubDirection ); // added by Flugente
|
||||
void EVENT_SoldierApplyItemToPerson( INT32 sGridNo, UINT8 ubDirection ); // added by Flugente
|
||||
void EVENT_SoldierInteractiveAction( INT32 sGridNo, UINT16 usActionType ); // added by Flugente
|
||||
|
||||
BOOLEAN EVENT_InternalGetNewSoldierPath( INT32 sDestGridNo, UINT16 usMovementAnim, BOOLEAN fFromUI, BOOLEAN fForceRestart );
|
||||
void EVENT_InternalSetSoldierDestination( UINT16 usNewDirection, BOOLEAN fFromMove, UINT16 usAnimState );
|
||||
@@ -1935,6 +1938,9 @@ public:
|
||||
|
||||
// Flugente: chance to defeat a water snake instead of being hit by it
|
||||
UINT8 GetWaterSnakeDefenseChance( );
|
||||
|
||||
// Flugente: interactive actions
|
||||
UINT16 GetInteractiveActionSkill( INT32 sGridNo, UINT8 usLevel, UINT16 usType );
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}; // SOLDIERTYPE;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "renderworld.h"
|
||||
#include "strategicmap.h"
|
||||
#include "rotting corpses.h"
|
||||
#include "WorldDat.h" // added by Flugente
|
||||
#endif
|
||||
|
||||
extern BOOLEAN DoesSAMExistHere( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ, INT32 sGridNo );
|
||||
@@ -590,6 +591,135 @@ BOOLEAN IsFortificationPossibleAtGridNo( INT32 sGridNo )
|
||||
return( pStructure == NULL );
|
||||
}
|
||||
|
||||
UINT16 InteractiveActionPossibleAtGridNo( INT32 sGridNo, UINT8 usLevel, UINT16& arusStructIndex )
|
||||
{
|
||||
arusStructIndex = 0;
|
||||
|
||||
STRUCTURE * pStruct = FindStructure( sGridNo, (STRUCTURE_GENERIC) );
|
||||
if ( pStruct )
|
||||
{
|
||||
// if this is a multi-tile structure, be sure to use the base gridno
|
||||
if ( !(pStruct->fFlags & STRUCTURE_BASE_TILE) )
|
||||
{
|
||||
pStruct = FindBaseStructure( pStruct );
|
||||
|
||||
if ( !pStruct )
|
||||
return INTERACTIVE_STRUCTURE_NO_ACTION;
|
||||
}
|
||||
|
||||
LEVELNODE* pNode = FindLevelNodeBasedOnStructure( pStruct->sGridNo, pStruct );
|
||||
|
||||
if ( pNode )
|
||||
{
|
||||
UINT16 usIndex = pNode->usIndex;
|
||||
UINT32 uiTileType = 0;
|
||||
if ( GetTileType( usIndex, &uiTileType ) )
|
||||
{
|
||||
// we loop over each action and determine whether it fits
|
||||
// multiple actions can fit, we chose whatever fits best
|
||||
// So, for example, we can set computers everywhere to be hackable with a generci result, and then define more precise results on specific computers
|
||||
// Other example: With just oen entry, with neither sector nor location set, we can make all water taps drinkable
|
||||
BOOLEAN foundmatch_precise = FALSE;
|
||||
BOOLEAN foundmatch_sector = FALSE;
|
||||
BOOLEAN foundmatch_any = FALSE;
|
||||
|
||||
UINT8 sector = SECTOR( gWorldSectorX, gWorldSectorY );
|
||||
|
||||
int foundindex = 0;
|
||||
if ( gTilesets[giCurrentTilesetID].TileSurfaceFilenames[uiTileType][0] )
|
||||
{
|
||||
for ( int i = 0; i < gMaxInteractiveStructureRead; ++i )
|
||||
{
|
||||
if ( !_strnicmp( gTilesets[giCurrentTilesetID].TileSurfaceFilenames[uiTileType], gInteractiveStructure[i].szTileSetName, 11 ) )
|
||||
{
|
||||
std::vector<UINT16> tmpvec = gInteractiveStructure[i].tileindexvector;
|
||||
|
||||
std::vector<UINT16>::iterator it = std::find( tmpvec.begin( ), tmpvec.end( ), pStruct->pDBStructureRef->pDBStructure->usStructureNumber );
|
||||
|
||||
if ( it != tmpvec.end( ) )
|
||||
{
|
||||
if ( gInteractiveStructure[i].sector == sector && gInteractiveStructure[i].sectorlevel == gbWorldSectorZ )
|
||||
{
|
||||
foundmatch_sector = TRUE;
|
||||
foundindex = i;
|
||||
|
||||
if ( gInteractiveStructure[i].sLevel == usLevel || gInteractiveStructure[i].sLevel == -1 )
|
||||
{
|
||||
std::vector<INT32> tmpgridnovec = gInteractiveStructure[i].gridnovector;
|
||||
|
||||
std::vector<INT32>::iterator it_gridno = std::find( tmpgridnovec.begin( ), tmpgridnovec.end( ), pStruct->sGridNo );
|
||||
|
||||
if ( it_gridno != tmpgridnovec.end( ) )
|
||||
{
|
||||
foundmatch_precise = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// some actions cen be defined everywhere
|
||||
else if ( !foundmatch_sector && gInteractiveStructure[i].sector == -1 && gInteractiveStructure[i].sectorlevel == -1 )
|
||||
{
|
||||
foundmatch_any = TRUE;
|
||||
foundindex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// otherwise, check first tileset (GENERIC 1)
|
||||
else if ( gTilesets[0].TileSurfaceFilenames[uiTileType][0] )
|
||||
{
|
||||
for ( int i = 0; i < gMaxInteractiveStructureRead; ++i )
|
||||
{
|
||||
if ( !_strnicmp( gTilesets[0].TileSurfaceFilenames[uiTileType], gInteractiveStructure[i].szTileSetName, 11 ) )
|
||||
{
|
||||
std::vector<UINT16> tmpvec = gInteractiveStructure[i].tileindexvector;
|
||||
|
||||
std::vector<UINT16>::iterator it = std::find( tmpvec.begin( ), tmpvec.end( ), pStruct->pDBStructureRef->pDBStructure->usStructureNumber );
|
||||
|
||||
if ( it != tmpvec.end() )
|
||||
{
|
||||
if ( gInteractiveStructure[i].sector == sector && gInteractiveStructure[i].sectorlevel == gbWorldSectorZ )
|
||||
{
|
||||
foundmatch_sector = TRUE;
|
||||
foundindex = i;
|
||||
|
||||
if ( gInteractiveStructure[i].sLevel == usLevel || gInteractiveStructure[i].sLevel == -1 )
|
||||
{
|
||||
std::vector<INT32> tmpgridnovec = gInteractiveStructure[i].gridnovector;
|
||||
|
||||
std::vector<INT32>::iterator it_gridno = std::find( tmpgridnovec.begin( ), tmpgridnovec.end( ), pStruct->sGridNo );
|
||||
|
||||
if ( it_gridno != tmpgridnovec.end() )
|
||||
{
|
||||
foundmatch_precise = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( !foundmatch_sector && gInteractiveStructure[i].sector == -1 && gInteractiveStructure[i].sectorlevel == -1 )
|
||||
{
|
||||
foundmatch_any = TRUE;
|
||||
foundindex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( foundmatch_any || foundmatch_sector || foundmatch_precise )
|
||||
{
|
||||
arusStructIndex = foundindex;
|
||||
|
||||
return gInteractiveStructure[foundindex].sActionType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return INTERACTIVE_STRUCTURE_NO_ACTION;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN IsCutWireFenceAtGridNo( INT32 sGridNo )
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ BOOLEAN IsCutWireFenceAtGridNo( INT32 sGridNo );
|
||||
BOOLEAN IsRepairableStructAtGridNo( INT32 sGridNo, UINT8 *pubID );
|
||||
BOOLEAN IsRefuelableStructAtGridNo( INT32 sGridNo, UINT8 *pubID );
|
||||
BOOLEAN IsFortificationPossibleAtGridNo( INT32 sGridNo ); // added by Flugente
|
||||
|
||||
UINT16 InteractiveActionPossibleAtGridNo( INT32 sGridNo, UINT8 usLevel, UINT16& arusStructIndex ); // added by Flugente
|
||||
|
||||
BOOLEAN IsRoofPresentAtGridNo( INT32 sGridNo );
|
||||
|
||||
|
||||
@@ -1144,6 +1144,10 @@
|
||||
RelativePath=".\XML_IncompatibleAttachments.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_InteractiveTiles.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_ItemAdjustments.cpp"
|
||||
>
|
||||
|
||||
@@ -1146,6 +1146,10 @@
|
||||
RelativePath="XML_IncompatibleAttachments.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="XML_InteractiveTiles.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_ItemAdjustments.cpp"
|
||||
>
|
||||
|
||||
@@ -223,6 +223,7 @@
|
||||
<ClCompile Include="XML_HiddenNames.cpp" />
|
||||
<ClCompile Include="XML_IMPItemChoices.cpp" />
|
||||
<ClCompile Include="XML_IncompatibleAttachments.cpp" />
|
||||
<ClCompile Include="XML_InteractiveTiles.cpp" />
|
||||
<ClCompile Include="XML_ItemAdjustments.cpp" />
|
||||
<ClCompile Include="XML_Keys.cpp" />
|
||||
<ClCompile Include="XML_Launchable.cpp" />
|
||||
|
||||
@@ -562,6 +562,9 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_IncompatibleAttachments.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_InteractiveTiles.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_Launchable.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
|
||||
@@ -224,6 +224,7 @@
|
||||
<ClCompile Include="XML_HiddenNames.cpp" />
|
||||
<ClCompile Include="XML_IMPItemChoices.cpp" />
|
||||
<ClCompile Include="XML_IncompatibleAttachments.cpp" />
|
||||
<ClCompile Include="XML_InteractiveTiles.cpp" />
|
||||
<ClCompile Include="XML_ItemAdjustments.cpp" />
|
||||
<ClCompile Include="XML_Keys.cpp" />
|
||||
<ClCompile Include="XML_Launchable.cpp" />
|
||||
|
||||
@@ -701,5 +701,8 @@
|
||||
<ClCompile Include="XML_MilitiaIndividual.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_InteractiveTiles.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -467,7 +467,7 @@ void EndTurnEvents( void )
|
||||
UINT32 cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
||||
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ++cnt, ++pSoldier)
|
||||
{
|
||||
if ( pSoldier->bActive && pSoldier->stats.bLife > 0 && !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) && !( AM_A_ROBOT( pSoldier ) ) )
|
||||
if ( pSoldier->bActive && pSoldier->stats.bLife > 0 )//&& !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) && !( AM_A_ROBOT( pSoldier ) ) )
|
||||
{
|
||||
// Flugente: update multi-turn actions
|
||||
pSoldier->UpdateMultiTurnAction();
|
||||
|
||||
+42
-6
@@ -57,6 +57,7 @@ UINT8 HandleTinCanCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorF
|
||||
UINT8 HandleFortificationCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); //added by Flugente
|
||||
UINT8 HandleHandcuffCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); //added by Flugente
|
||||
UINT8 HandleApplyItemCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); //added by Flugente
|
||||
UINT8 HandleHackCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); //added by Flugente
|
||||
|
||||
extern BOOLEAN HandleCheckForBadChangeToGetThrough( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pTargetSoldier, INT32 sTargetGridNo , INT8 bLevel );
|
||||
|
||||
@@ -323,11 +324,13 @@ UINT8 GetProperItemCursor( UINT8 ubSoldierID, UINT16 ubItemIndex, INT32 usMapPos
|
||||
ubCursorID = HandleApplyItemCursor( pSoldier, sTargetGridNo, uiCursorFlags );
|
||||
break;
|
||||
|
||||
case INVALIDCURS:
|
||||
|
||||
ubCursorID = INVALID_ACTION_UICURSOR;
|
||||
case INTERACTIVEACTIONCURS:
|
||||
ubCursorID = HandleHackCursor( pSoldier, sTargetGridNo, uiCursorFlags );
|
||||
break;
|
||||
|
||||
case INVALIDCURS:
|
||||
ubCursorID = INVALID_ACTION_UICURSOR;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
||||
@@ -342,11 +345,9 @@ UINT8 GetProperItemCursor( UINT8 ubSoldierID, UINT16 ubItemIndex, INT32 usMapPos
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return( ubCursorID );
|
||||
}
|
||||
|
||||
|
||||
// WANNE: Shows the target cursor over the enemy soldier
|
||||
UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEAN fShowAPs, BOOLEAN fRecalc, UINT32 uiCursorFlags )
|
||||
{
|
||||
@@ -2276,6 +2277,27 @@ UINT8 HandleApplyItemCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCurs
|
||||
return( APPLYITEM_RED_UICURSOR );
|
||||
}
|
||||
|
||||
UINT8 HandleHackCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags )
|
||||
{
|
||||
// DRAW PATH TO GUY
|
||||
HandleUIMovementCursor( pSoldier, uiCursorFlags, sGridNo, MOVEUI_TARGET_INTERACTIVEACTION );
|
||||
|
||||
UINT16 structindex;
|
||||
UINT16 possibleaction = InteractiveActionPossibleAtGridNo( sGridNo, pSoldier->pathing.bLevel, structindex );
|
||||
UINT16 skill = pSoldier->GetInteractiveActionSkill( sGridNo, pSoldier->pathing.bLevel, possibleaction );
|
||||
|
||||
if ( possibleaction == INTERACTIVE_STRUCTURE_HACKABLE )
|
||||
return skill ? HACK_GREY_UICURSOR : HACK_RED_UICURSOR;
|
||||
else if ( possibleaction == INTERACTIVE_STRUCTURE_READFILE )
|
||||
return skill ? READFILE_GREY_UICURSOR : READFILE_RED_UICURSOR;
|
||||
else if ( possibleaction == INTERACTIVE_STRUCTURE_WATERTAP )
|
||||
return skill ? WATERTAP_GREY_UICURSOR : WATERTAP_RED_UICURSOR;
|
||||
else if ( possibleaction == INTERACTIVE_STRUCTURE_SODAMACHINE )
|
||||
return skill ? SODAMACHINE_GREY_UICURSOR : SODAMACHINE_RED_UICURSOR;
|
||||
|
||||
return NO_UICURSOR;
|
||||
}
|
||||
|
||||
void HandleEndConfirmCursor( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
UINT16 usInHand;
|
||||
@@ -2784,7 +2806,7 @@ UINT8 GetActionModeCursor( SOLDIERTYPE *pSoldier )
|
||||
else
|
||||
return ( TRAJECTORYCURS );
|
||||
}
|
||||
if ( pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO || ( pSoldier->bWeaponMode == WM_AUTOFIRE && Item[pSoldier->inv[HANDPOS].usItem].grenadelauncher ) )
|
||||
else if ( pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO || ( pSoldier->bWeaponMode == WM_AUTOFIRE && Item[pSoldier->inv[HANDPOS].usItem].grenadelauncher ) )
|
||||
{
|
||||
if ( gGameSettings.fOptions [ TOPTION_GL_BURST_CURSOR ] )
|
||||
return( TARGETCURS );
|
||||
@@ -2823,6 +2845,20 @@ UINT8 GetActionModeCursor( SOLDIERTYPE *pSoldier )
|
||||
if ( gGameExternalOptions.fAllowPrisonerSystem && HasItemFlag(usInHand, HANDCUFFS) )
|
||||
ubCursor = HANDCUFFCURS;
|
||||
|
||||
// Flugente: interactive actions
|
||||
// we only check whether an action is possible in principle, not whether this particular guy can do it. That way we know an action is possible here even if we can't perform it at the moment.
|
||||
// only do this if the item doesn't already allow us to do something else
|
||||
if ( ubCursor == INVALIDCURS || usInHand == NONE )
|
||||
{
|
||||
INT32 usMapPos = NOWHERE;
|
||||
GetMouseMapPos( &usMapPos );
|
||||
|
||||
UINT16 structindex;
|
||||
UINT16 possibleaction = InteractiveActionPossibleAtGridNo( usMapPos, pSoldier->pathing.bLevel, structindex );
|
||||
if ( possibleaction > INTERACTIVE_STRUCTURE_NO_ACTION )
|
||||
ubCursor = INTERACTIVEACTIONCURS;
|
||||
}
|
||||
|
||||
// Flugente: apply misc items to other soldiers
|
||||
if ( ItemCanBeAppliedToOthers( usInHand ) )
|
||||
{
|
||||
|
||||
@@ -172,6 +172,7 @@ typedef PARSE_STAGE;
|
||||
#define SECTORLEVEL1NAMESFILENAME "Map\\SectorNamesLevel_1.xml"
|
||||
#define SECTORLEVEL2NAMESFILENAME "Map\\SectorNamesLevel_2.xml"
|
||||
#define SECTORLEVEL3NAMESFILENAME "Map\\SectorNamesLevel_3.xml"
|
||||
#define INTERACTIVEACTIONSFILENAME "Map\\InteractiveActions.xml"
|
||||
|
||||
#define GARRISONFILENAME "Army\\GarrisonGroups.xml"
|
||||
#define PATROLFILENAME "Army\\PatrolGroups.xml"
|
||||
@@ -326,6 +327,10 @@ extern BOOLEAN WriteStructureDeconstructStats();
|
||||
extern BOOLEAN ReadInStructureConstructStats(STR fileName);
|
||||
extern BOOLEAN WriteStructureConstructStats();
|
||||
|
||||
// Flugente: interactive actions
|
||||
extern BOOLEAN ReadInInteractiveActionsStats( STR fileName );
|
||||
extern BOOLEAN WriteInteractiveActionsStats( );
|
||||
|
||||
// Flugente: merchants
|
||||
extern BOOLEAN ReadInMerchantStats(STR fileName);
|
||||
extern BOOLEAN WriteMerchantStats();
|
||||
|
||||
@@ -135,6 +135,7 @@ backgroundStartElementHandle(void *userData, const XML_Char *name, const XML_Cha
|
||||
strcmp(name, "smoker" ) == 0 ||
|
||||
strcmp(name, "croucheddefense" ) == 0 ||
|
||||
strcmp(name, "fortify_assignment" ) == 0 ||
|
||||
strcmp(name, "hackerskill" ) == 0 ||
|
||||
strcmp(name, "druguse") == 0 ||
|
||||
strcmp(name, "xenophobic") == 0 ||
|
||||
strcmp(name, "corruptionspread") == 0 ||
|
||||
@@ -579,6 +580,11 @@ backgroundEndElementHandle(void *userData, const XML_Char *name)
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curBackground.value[BG_FORTIFY_ASSIGNMENT] = min( 200, max( -50, (INT16)atol( pData->szCharData ) ) );
|
||||
}
|
||||
else if ( strcmp( name, "hackerskill" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curBackground.value[BG_HACKERSKILL] = min( 100, max( 0, (INT16)atol( pData->szCharData ) ) );
|
||||
}
|
||||
else if(strcmp(name, "druguse") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
/**
|
||||
* @file
|
||||
* @author Flugente (bears-pit.com)
|
||||
*/
|
||||
|
||||
#ifdef PRECOMPILEDHEADERS
|
||||
#include "Tactical All.h"
|
||||
#else
|
||||
#include "sgp.h"
|
||||
#include "Debug Control.h"
|
||||
#include "expat.h"
|
||||
#include "gamesettings.h"
|
||||
#include "XML.h"
|
||||
#include "FileMan.h"
|
||||
#include "Handle Items.h"
|
||||
#endif
|
||||
|
||||
INTERACTIVE_STRUCTURE gInteractiveStructure[INTERACTIVE_STRUCTURE_MAX];
|
||||
UINT32 gMaxInteractiveStructureRead = 0;
|
||||
|
||||
struct
|
||||
{
|
||||
PARSE_STAGE curElement;
|
||||
|
||||
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH + 1];
|
||||
INTERACTIVE_STRUCTURE curFood;
|
||||
INTERACTIVE_STRUCTURE* curArray;
|
||||
|
||||
UINT32 maxArraySize;
|
||||
UINT32 curIndex;
|
||||
UINT32 currentDepth;
|
||||
UINT32 maxReadDepth;
|
||||
}
|
||||
typedef interactiveactionsParseData;
|
||||
|
||||
static void XMLCALL
|
||||
interactiveactionsStartElementHandle( void *userData, const XML_Char *name, const XML_Char **atts )
|
||||
{
|
||||
interactiveactionsParseData * pData = (interactiveactionsParseData *)userData;
|
||||
|
||||
if ( pData->currentDepth <= pData->maxReadDepth ) //are we reading this element?
|
||||
{
|
||||
if ( strcmp( name, "INTERACTIVEACTIONS" ) == 0 && pData->curElement == ELEMENT_NONE )
|
||||
{
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
memset( pData->curArray, 0, sizeof(INTERACTIVE_STRUCTURE)*pData->maxArraySize );
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if ( strcmp( name, "ACTION" ) == 0 && pData->curElement == ELEMENT_LIST )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
memset( &pData->curFood, 0, sizeof(INTERACTIVE_STRUCTURE) );
|
||||
|
||||
pData->curFood.reset( );
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if ( pData->curElement == ELEMENT &&
|
||||
(strcmp( name, "SectorGrid" ) == 0 ||
|
||||
strcmp( name, "sectorlevel" ) == 0 ||
|
||||
strcmp( name, "szTileSetName" ) == 0 ||
|
||||
strcmp( name, "usTileIndex" ) == 0 ||
|
||||
strcmp( name, "sStructureGridno" ) == 0 ||
|
||||
strcmp( name, "sLevel" ) == 0 ||
|
||||
strcmp( name, "sActionType" ) == 0 ||
|
||||
strcmp( name, "difficulty" ) == 0 ||
|
||||
strcmp( name, "luaactionid" ) == 0
|
||||
) )
|
||||
{
|
||||
pData->curElement = ELEMENT_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
pData->szCharData[0] = '\0';
|
||||
}
|
||||
|
||||
pData->currentDepth++;
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
interactiveactionsDataHandle( void *userData, const XML_Char *str, int len )
|
||||
{
|
||||
interactiveactionsParseData * pData = (interactiveactionsParseData *)userData;
|
||||
|
||||
if ( (pData->currentDepth <= pData->maxReadDepth) &&
|
||||
(strlen( pData->szCharData ) < MAX_CHAR_DATA_LENGTH)
|
||||
)
|
||||
{
|
||||
strncat( pData->szCharData, str, __min( (unsigned int)len, MAX_CHAR_DATA_LENGTH - strlen( pData->szCharData ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
interactiveactionsEndElementHandle( void *userData, const XML_Char *name )
|
||||
{
|
||||
static std::vector<UINT16> tileindexvector;
|
||||
static std::vector<INT32> gridnovector;
|
||||
|
||||
interactiveactionsParseData * pData = (interactiveactionsParseData *)userData;
|
||||
|
||||
if ( pData->currentDepth <= pData->maxReadDepth ) //we're at the end of an element that we've been reading
|
||||
{
|
||||
if ( strcmp( name, "INTERACTIVEACTIONS" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT_NONE;
|
||||
|
||||
gMaxInteractiveStructureRead = pData->curIndex;
|
||||
}
|
||||
else if ( strcmp( name, "ACTION" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
if ( pData->curIndex < pData->maxArraySize )
|
||||
{
|
||||
// for whatever reasons the game crashes in VS2008 Release builds when copying over the tilevector
|
||||
// this seems odd, as this works just fine in VS2010 and VS2013, and also works in VS205 debug builds
|
||||
// for now, copy over the content by hand
|
||||
pData->curArray[pData->curIndex].sector = pData->curFood.sector;
|
||||
pData->curArray[pData->curIndex].sectorlevel = pData->curFood.sectorlevel;
|
||||
strncpy( pData->curArray[pData->curIndex].szTileSetName, pData->curFood.szTileSetName, 20 );
|
||||
pData->curArray[pData->curIndex].tileindexvector = tileindexvector;
|
||||
pData->curArray[pData->curIndex].gridnovector = gridnovector;
|
||||
pData->curArray[pData->curIndex].sLevel = pData->curFood.sLevel;
|
||||
pData->curArray[pData->curIndex].sActionType = pData->curFood.sActionType;
|
||||
pData->curArray[pData->curIndex].difficulty = pData->curFood.difficulty;
|
||||
pData->curArray[pData->curIndex].luaactionid = pData->curFood.luaactionid;
|
||||
|
||||
tileindexvector.clear( );
|
||||
tileindexvector.resize( 0 );
|
||||
|
||||
gridnovector.clear();
|
||||
gridnovector.resize( 0 );
|
||||
}
|
||||
|
||||
pData->curIndex++;
|
||||
}
|
||||
|
||||
else if ( strcmp( name, "SectorGrid" ) == 0 )
|
||||
{
|
||||
UINT8 x, y;
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
y = (UINT8)pData->szCharData[0] & 0x1F;
|
||||
x = (UINT8)atol( &pData->szCharData[1] );
|
||||
if ( x > 0 && x <= 16 && y > 0 && y <= 16 )
|
||||
{
|
||||
pData->curFood.sector = SECTOR(x, y);
|
||||
}
|
||||
}
|
||||
else if ( strcmp( name, "sectorlevel" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curFood.sectorlevel = min( 3, max(-1, (INT8)atol( pData->szCharData ) ) );
|
||||
}
|
||||
else if ( strcmp( name, "szTileSetName" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
strncpy( pData->curFood.szTileSetName, pData->szCharData, 20 );
|
||||
}
|
||||
else if ( strcmp( name, "usTileIndex" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
tileindexvector.push_back( (UINT16)atol( pData->szCharData ) );
|
||||
}
|
||||
else if ( strcmp( name, "sStructureGridno" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
gridnovector.push_back( (INT32)atol( pData->szCharData ) );
|
||||
}
|
||||
else if ( strcmp( name, "sLevel" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curFood.sLevel = min( 1, max( 0, (INT8)atol( pData->szCharData ) ) );
|
||||
}
|
||||
else if ( strcmp( name, "sActionType" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curFood.sActionType = (UINT16)atol( pData->szCharData );
|
||||
}
|
||||
else if ( strcmp( name, "difficulty" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curFood.difficulty = (INT32)atol( pData->szCharData );
|
||||
}
|
||||
else if ( strcmp( name, "luaactionid" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curFood.luaactionid = (INT32)atol( pData->szCharData );
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
|
||||
pData->currentDepth--;
|
||||
}
|
||||
|
||||
BOOLEAN ReadInInteractiveActionsStats( STR fileName )
|
||||
{
|
||||
HWFILE hFile;
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8 * lpcBuffer;
|
||||
XML_Parser parser = XML_ParserCreate( NULL );
|
||||
|
||||
interactiveactionsParseData pData;
|
||||
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Loading InteractiveActions.xml" );
|
||||
|
||||
// Open merges file
|
||||
hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE );
|
||||
if ( !hFile )
|
||||
return(FALSE);
|
||||
|
||||
uiFSize = FileGetSize( hFile );
|
||||
lpcBuffer = (CHAR8 *)MemAlloc( uiFSize + 1 );
|
||||
|
||||
//Read in block
|
||||
if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) )
|
||||
{
|
||||
MemFree( lpcBuffer );
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
lpcBuffer[uiFSize] = 0; //add a null terminator
|
||||
|
||||
FileClose( hFile );
|
||||
|
||||
XML_SetElementHandler( parser, interactiveactionsStartElementHandle, interactiveactionsEndElementHandle );
|
||||
XML_SetCharacterDataHandler( parser, interactiveactionsDataHandle );
|
||||
|
||||
memset( &pData, 0, sizeof(pData) );
|
||||
pData.maxArraySize = INTERACTIVE_STRUCTURE_MAX;
|
||||
pData.curIndex = 0;
|
||||
pData.curFood.reset( );
|
||||
pData.curArray = gInteractiveStructure;
|
||||
|
||||
XML_SetUserData( parser, &pData );
|
||||
|
||||
if ( !XML_Parse( parser, lpcBuffer, uiFSize, TRUE ) )
|
||||
{
|
||||
CHAR8 errorBuf[511];
|
||||
|
||||
sprintf( errorBuf, "XML Parser Error in InteractiveActions.xml: %s at line %d", XML_ErrorString( XML_GetErrorCode( parser ) ), XML_GetCurrentLineNumber( parser ) );
|
||||
LiveMessage( errorBuf );
|
||||
|
||||
MemFree( lpcBuffer );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MemFree( lpcBuffer );
|
||||
|
||||
XML_ParserFree( parser );
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
@@ -128,6 +128,18 @@ CursorFileData CursorFileDatabase[] =
|
||||
{ "CURSORS\\apply_r.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL }, // Flugente: apply items - still needs animation
|
||||
{ "CURSORS\\apply.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL }, // yes, the red one is the 'valid' one - just like for taking items
|
||||
|
||||
{ "CURSORS\\hack.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL}, // Flugente: hack
|
||||
{ "CURSORS\\hack_r.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL},
|
||||
|
||||
{ "CURSORS\\readfile.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL}, // Flugente: read file
|
||||
{ "CURSORS\\readfile_r.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL},
|
||||
|
||||
{"CURSORS\\watertap.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL}, // Flugente: watertap
|
||||
{"CURSORS\\watertap_r.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL},
|
||||
|
||||
{"CURSORS\\sodamachine.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL}, // Flugente: soda machine
|
||||
{"CURSORS\\sodamachine_r.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL},
|
||||
|
||||
{ "CURSORS\\can_01.sti" , FALSE, 0, 0, 0, NULL },
|
||||
{ "CURSORS\\can_02.sti" , FALSE, 0, 0, 0, NULL },
|
||||
{ "CURSORS\\cur_tagr_ncth.sti" , FALSE, 0, ANIMATED_CURSOR, 7, NULL },
|
||||
@@ -1233,6 +1245,66 @@ CursorData CursorDatabase[] =
|
||||
0, 0, 0, 0, 0,
|
||||
2, CENTER_CURSOR, CENTER_CURSOR, 0, 0 , 0, 0 },
|
||||
|
||||
// Flugente: hack
|
||||
{ C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR,
|
||||
C_HACK, 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
2, CENTER_CURSOR, CENTER_CURSOR, 0, 0, 0, 0},
|
||||
|
||||
{ C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR,
|
||||
C_HACK_RED, 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
2, CENTER_CURSOR, CENTER_CURSOR, 0, 0, 0, 0},
|
||||
|
||||
// Flugente: read file
|
||||
{C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR,
|
||||
C_READFILE, 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
2, CENTER_CURSOR, CENTER_CURSOR, 0, 0, 0, 0},
|
||||
|
||||
{C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR,
|
||||
C_READFILE_RED, 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
2, CENTER_CURSOR, CENTER_CURSOR, 0, 0, 0, 0},
|
||||
|
||||
// Flugente: watertap
|
||||
{C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR,
|
||||
C_WATERTAP, 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
2, CENTER_CURSOR, CENTER_CURSOR, 0, 0, 0, 0},
|
||||
|
||||
{C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR,
|
||||
C_WATERTAP_RED, 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
2, CENTER_CURSOR, CENTER_CURSOR, 0, 0, 0, 0},
|
||||
|
||||
// Flugente: soad machine
|
||||
{C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR,
|
||||
C_SODAMACHINE, 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
2, CENTER_CURSOR, CENTER_CURSOR, 0, 0, 0, 0},
|
||||
|
||||
{C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR,
|
||||
C_SODAMACHINE_RED, 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
2, CENTER_CURSOR, CENTER_CURSOR, 0, 0, 0, 0},
|
||||
|
||||
{ C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR,
|
||||
C_FUEL , 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR,
|
||||
0, 0, 0, 0, 0,
|
||||
|
||||
@@ -162,6 +162,18 @@ typedef enum
|
||||
CURSOR_APPLYITEM,
|
||||
CURSOR_APPLYITEM_RED,
|
||||
|
||||
CURSOR_HACK,
|
||||
CURSOR_HACK_RED,
|
||||
|
||||
CURSOR_READFILE,
|
||||
CURSOR_READFILE_RED,
|
||||
|
||||
CURSOR_WATERTAP,
|
||||
CURSOR_WATERTAP_RED,
|
||||
|
||||
CURSOR_SODAMACHINE,
|
||||
CURSOR_SODAMACHINE_RED,
|
||||
|
||||
CURSOR_FUEL,
|
||||
CURSOR_FUEL_RED,
|
||||
|
||||
@@ -241,6 +253,14 @@ typedef enum
|
||||
C_HANDCUFFS_RED,
|
||||
C_APPLYITEM,
|
||||
C_APPLYITEM_RED,
|
||||
C_HACK,
|
||||
C_HACK_RED,
|
||||
C_READFILE,
|
||||
C_READFILE_RED,
|
||||
C_WATERTAP,
|
||||
C_WATERTAP_RED,
|
||||
C_SODAMACHINE,
|
||||
C_SODAMACHINE_RED,
|
||||
C_FUEL,
|
||||
C_FUEL_RED,
|
||||
C_ACTIONMODERED_NCTH,
|
||||
|
||||
@@ -885,6 +885,7 @@ enum
|
||||
STR_MTA_NONE,
|
||||
STR_MTA_FORTIFY,
|
||||
STR_MTA_REMOVE_FORTIFY,
|
||||
STR_MTA_HACK,
|
||||
STR_MTA_CANCEL,
|
||||
STR_MTA_CANNOT_BUILD,
|
||||
|
||||
@@ -2977,6 +2978,9 @@ extern STR16 szSnakeText[];
|
||||
// Flugente: militia resources
|
||||
extern STR16 szSMilitiaResourceText[];
|
||||
|
||||
// Flugente: interactive actions
|
||||
extern STR16 szInteractiveActionText[];
|
||||
|
||||
#define TACTICAL_INVENTORY_DIALOG_NUM 16
|
||||
#define TACTICAL_COVER_DIALOG_NUM 16
|
||||
|
||||
|
||||
@@ -275,6 +275,7 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at
|
||||
strcmp(name, "CrowbarModifier") == 0 ||
|
||||
strcmp(name, "DisarmModifier") == 0 ||
|
||||
strcmp(name, "RepairModifier") == 0 ||
|
||||
strcmp(name, "usHackingModifier" ) == 0 ||
|
||||
|
||||
strcmp(name, "usActionItemFlag") == 0 ||
|
||||
strcmp(name, "clothestype") == 0 ||
|
||||
@@ -1396,6 +1397,11 @@ itemEndElementHandle(void *userData, const XML_Char *name)
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curItem.RepairModifier = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
else if ( strcmp( name, "usHackingModifier" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curItem.usHackingModifier = min(100, (UINT8)atol( pData->szCharData ) );
|
||||
}
|
||||
else if(strcmp(name, "DamageChance") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
@@ -2106,6 +2112,7 @@ BOOLEAN WriteItemStats()
|
||||
FilePrintf(hFile, "\t\t<CrowbarModifier>%d</CrowbarModifier>\r\n", Item[cnt].CrowbarModifier );
|
||||
FilePrintf(hFile, "\t\t<DisarmModifier>%d</DisarmModifier>\r\n", Item[cnt].DisarmModifier );
|
||||
FilePrintf(hFile, "\t\t<RepairModifier>%d</RepairModifier>\r\n", Item[cnt].RepairModifier );
|
||||
FilePrintf(hFile, "\t\t<usHackingModifier>%d</usHackingModifier>\r\n", Item[cnt].usHackingModifier );
|
||||
|
||||
FilePrintf(hFile,"\t\t<DamageChance>%d</DamageChance>\r\n", Item[cnt].usDamageChance );
|
||||
FilePrintf(hFile,"\t\t<DirtIncreaseFactor>%4.2f</DirtIncreaseFactor>\r\n", Item[cnt].dirtIncreaseFactor );
|
||||
|
||||
+18
-1
@@ -8832,7 +8832,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"敌人不肯拿你当囚犯 - 他们宁愿你死!", //L"The enemy refuses to take you as prisoners - they prefer you dead!",
|
||||
L"这些可以在 INI 设置关闭。", // L"This behaviour is set OFF in your ini settings.",
|
||||
L"%s释放了%s!", //L"%s has freed %s!",
|
||||
L"囚犯会暴露高级军官的位置 %s!", //L"A prisoner revealed the location of a high-ranking army officer in %s!",
|
||||
L"A high-ranking army officer in %s has been revealed!", // TODO.Translate
|
||||
L"敌方首领会拒绝即使被认为投降!", //L"The enemy leader refuses to even consider surrender!",
|
||||
L"%d 囚犯自愿加入我军。", //L"%d prisoners volunteered to join our forces.",
|
||||
};
|
||||
@@ -8842,6 +8842,7 @@ STR16 szMTATextStr[]=
|
||||
L"空无一物",
|
||||
L"建造掩体", //L"building a fortification",
|
||||
L"拆除掩体", //L"removing a fortification",
|
||||
L"hacking", // TODO.Translate
|
||||
L"%s必须停止%s", //L"%s had to stop %s.",
|
||||
L"所选的路障无法再该分区建造",
|
||||
};
|
||||
@@ -8953,6 +8954,7 @@ STR16 szBackgroundText_Value[]=
|
||||
L"非吸烟者", //L"Nonsmoker",
|
||||
L" %s%d%% 如果敌人 CTH 蹲在厚覆盖他们的方向\n", //L" %s%d%% enemy CTH if crouched against thick cover in their direction\n",
|
||||
L" %s%d%% building speed\n",
|
||||
L" hacking skill: %s%d ", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szBackgroundTitleText[] =
|
||||
@@ -11160,6 +11162,21 @@ STR16 szSMilitiaResourceText[] =
|
||||
L"Not enough resources to train militia!",
|
||||
};
|
||||
|
||||
STR16 szInteractiveActionText[] =
|
||||
{
|
||||
L"%s starts hacking.",
|
||||
L"%s accesses the computer, but finds nothing of interest.",
|
||||
L"%s is not skilled enough to hack the computer.",
|
||||
L"%s reads the file, but learns nothing new.",
|
||||
|
||||
L"%s can't make sense out of this.",
|
||||
L"%s couldn't use the watertap.",
|
||||
L"%s has bought a %s.",
|
||||
L"%s doesn't have enough money. That's just embarassing.",
|
||||
|
||||
L"%s drank from water tap",
|
||||
};
|
||||
|
||||
// WANNE: Some Chinese specific strings that needs to be in unicode!
|
||||
STR16 ChineseSpecString1 = L"%%"; //defined in _ChineseText.cpp as this file is already unicode
|
||||
STR16 ChineseSpecString2 = L"*%3d%%%%"; //defined in _ChineseText.cpp as this file is already unicode
|
||||
|
||||
+18
-1
@@ -8847,7 +8847,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"The enemy refuses to take you as prisoners - they prefer you dead!",
|
||||
L"This behaviour is set OFF in your ini settings.",
|
||||
L"%s has freed %s!",
|
||||
L"A prisoner revealed the location of a high-ranking army officer in %s!", // TODO.Translate
|
||||
L"A high-ranking army officer in %s has been revealed!", // TODO.Translate
|
||||
L"The enemy leader refuses to even consider surrender!",
|
||||
L"%d prisoners volunteered to join our forces.",
|
||||
};
|
||||
@@ -8857,6 +8857,7 @@ STR16 szMTATextStr[]= // TODO.Translate
|
||||
L"nothing",
|
||||
L"building a fortification",
|
||||
L"removing a fortification",
|
||||
L"hacking", // TODO.Translate
|
||||
L"%s had to stop %s.",
|
||||
L"The selected barricade cannot be built in this sector", // TODO.Translate
|
||||
};
|
||||
@@ -8970,6 +8971,7 @@ STR16 szBackgroundText_Value[]=
|
||||
L"Nonsmoker",
|
||||
L" %s%d%% enemy CTH if crouched against thick cover in their direction\n",
|
||||
L" %s%d%% building speed\n",
|
||||
L" hacking skill: %s%d ", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szBackgroundTitleText[] = // TODO.Translate
|
||||
@@ -11177,4 +11179,19 @@ STR16 szSMilitiaResourceText[] =
|
||||
L"Not enough resources to train militia!",
|
||||
};
|
||||
|
||||
STR16 szInteractiveActionText[] =
|
||||
{
|
||||
L"%s starts hacking.",
|
||||
L"%s accesses the computer, but finds nothing of interest.",
|
||||
L"%s is not skilled enough to hack the computer.",
|
||||
L"%s reads the file, but learns nothing new.",
|
||||
|
||||
L"%s can't make sense out of this.",
|
||||
L"%s couldn't use the watertap.",
|
||||
L"%s has bought a %s.",
|
||||
L"%s doesn't have enough money. That's just embarassing.",
|
||||
|
||||
L"%s drank from water tap",
|
||||
};
|
||||
|
||||
#endif //DUTCH
|
||||
|
||||
+18
-1
@@ -8830,7 +8830,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"The enemy refuses to take you as prisoners - they prefer you dead!",
|
||||
L"This behaviour is set OFF in your ini settings.",
|
||||
L"%s has freed %s!",
|
||||
L"A prisoner revealed the location of a high-ranking army officer in %s!",
|
||||
L"A high-ranking army officer in %s has been revealed!",
|
||||
L"The enemy leader refuses to even consider surrender!",
|
||||
L"%d prisoners volunteered to join our forces.",
|
||||
};
|
||||
@@ -8840,6 +8840,7 @@ STR16 szMTATextStr[]=
|
||||
L"nothing",
|
||||
L"building a fortification",
|
||||
L"removing a fortification",
|
||||
L"hacking",
|
||||
L"%s had to stop %s.",
|
||||
L"The selected barricade cannot be built in this sector",
|
||||
};
|
||||
@@ -8951,6 +8952,7 @@ STR16 szBackgroundText_Value[]=
|
||||
L" Nonsmoker",
|
||||
L" %s%d%% enemy CTH if crouched against thick cover in their direction\n",
|
||||
L" %s%d%% building speed\n",
|
||||
L" hacking skill: %s%d ",
|
||||
};
|
||||
|
||||
STR16 szBackgroundTitleText[] =
|
||||
@@ -11160,4 +11162,19 @@ STR16 szSMilitiaResourceText[] =
|
||||
L"Not enough resources to train militia!",
|
||||
};
|
||||
|
||||
STR16 szInteractiveActionText[] =
|
||||
{
|
||||
L"%s starts hacking.",
|
||||
L"%s accesses the computer, but finds nothing of interest.",
|
||||
L"%s is not skilled enough to hack the computer.",
|
||||
L"%s reads the file, but learns nothing new.",
|
||||
|
||||
L"%s can't make sense out of this.",
|
||||
L"%s couldn't use the watertap.",
|
||||
L"%s has bought a %s.",
|
||||
L"%s doesn't have enough money. That's just embarassing.",
|
||||
|
||||
L"%s drank from water tap",
|
||||
};
|
||||
|
||||
#endif //ENGLISH
|
||||
|
||||
+18
-1
@@ -8829,7 +8829,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"L'ennemi refuse votre reddition... Ils veulent vos têtes !",
|
||||
L"Ce comportement est désactivé dans vos fichiers ini.",
|
||||
L"%s a libéré %s !",
|
||||
L"A prisoner revealed the location of a high-ranking army officer in %s!", // TODO.Translate
|
||||
L"A high-ranking army officer in %s has been revealed!", // TODO.Translate
|
||||
L"The enemy leader refuses to even consider surrender!",
|
||||
L"%d prisoners volunteered to join our forces.",
|
||||
};
|
||||
@@ -8839,6 +8839,7 @@ STR16 szMTATextStr[]=
|
||||
L"rien, en fait.",
|
||||
L"la construction d'une fortification",
|
||||
L"le retrait d'une fortification",
|
||||
L"hacking", // TODO.Translate
|
||||
L"%s a dû arrêter... %s",
|
||||
L"Cette sorte de barricade ne peut pas être construite dans ce secteur",
|
||||
};
|
||||
@@ -8952,6 +8953,7 @@ STR16 szBackgroundText_Value[]=
|
||||
L"Nonsmoker",
|
||||
L" %s%d%% enemy CTH if crouched against thick cover in their direction\n",
|
||||
L" %s%d%% building speed\n",
|
||||
L" hacking skill: %s%d ", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szBackgroundTitleText[] =
|
||||
@@ -11159,4 +11161,19 @@ STR16 szSMilitiaResourceText[] =
|
||||
L"Not enough resources to train militia!",
|
||||
};
|
||||
|
||||
STR16 szInteractiveActionText[] =
|
||||
{
|
||||
L"%s starts hacking.",
|
||||
L"%s accesses the computer, but finds nothing of interest.",
|
||||
L"%s is not skilled enough to hack the computer.",
|
||||
L"%s reads the file, but learns nothing new.",
|
||||
|
||||
L"%s can't make sense out of this.",
|
||||
L"%s couldn't use the watertap.",
|
||||
L"%s has bought a %s.",
|
||||
L"%s doesn't have enough money. That's just embarassing.",
|
||||
|
||||
L"%s drank from water tap",
|
||||
};
|
||||
|
||||
#endif //FRENCH
|
||||
|
||||
+18
-1
@@ -8659,7 +8659,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"Der Feind weigert sich, Sie als Gefangenen zu nehmen - Er möchte Sie tod sehen!",
|
||||
L"Dieses Verhalten ist ausgeschaltet in der ja2_options.ini Datei.",
|
||||
L"%s hat %s befreit!",
|
||||
L"Ein Gefangener hat den Aufenthaltsort eines hochrangigen Offiziers in %s enthüllt!",
|
||||
L"A high-ranking army officer in %s has been revealed!", // TODO.Translate
|
||||
L"Der feindliche Anführer denkt nicht mal an Kapitulation!",
|
||||
L"%d Gefangene sind uns als Freiwillige beigetreten.",
|
||||
};
|
||||
@@ -8669,6 +8669,7 @@ STR16 szMTATextStr[]=
|
||||
L"nichts",
|
||||
L"baue eine Befestigung",
|
||||
L"entferne eine Befestigung",
|
||||
L"hacking", // TODO.Translate
|
||||
L"%s musste %s stoppen.",
|
||||
L"The selected barricade cannot be built in this sector", // TODO.Translate
|
||||
};
|
||||
@@ -8782,6 +8783,7 @@ STR16 szBackgroundText_Value[]=
|
||||
L"Nonsmoker",
|
||||
L" %s%d%% enemy CTH if crouched against thick cover in their direction\n",
|
||||
L" %s%d%% building speed\n",
|
||||
L" hacking skill: %s%d ", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szBackgroundTitleText[] = // TODO.Translate
|
||||
@@ -10989,4 +10991,19 @@ STR16 szSMilitiaResourceText[] =
|
||||
L"Not enough resources to train militia!",
|
||||
};
|
||||
|
||||
STR16 szInteractiveActionText[] =
|
||||
{
|
||||
L"%s starts hacking.",
|
||||
L"%s accesses the computer, but finds nothing of interest.",
|
||||
L"%s is not skilled enough to hack the computer.",
|
||||
L"%s reads the file, but learns nothing new.",
|
||||
|
||||
L"%s can't make sense out of this.",
|
||||
L"%s couldn't use the watertap.",
|
||||
L"%s has bought a %s.",
|
||||
L"%s doesn't have enough money. That's just embarassing.",
|
||||
|
||||
L"%s drank from water tap",
|
||||
};
|
||||
|
||||
#endif //GERMAN
|
||||
|
||||
+18
-1
@@ -8837,7 +8837,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"The enemy refuses to take you as prisoners - they prefer you dead!",
|
||||
L"This behaviour is set OFF in your ini settings.",
|
||||
L"%s has freed %s!",
|
||||
L"A prisoner revealed the location of a high-ranking army officer in %s!", // TODO.Translate
|
||||
L"A high-ranking army officer in %s has been revealed!", // TODO.Translate
|
||||
L"The enemy leader refuses to even consider surrender!",
|
||||
L"%d prisoners volunteered to join our forces.",
|
||||
};
|
||||
@@ -8847,6 +8847,7 @@ STR16 szMTATextStr[]= // TODO.Translate
|
||||
L"nothing",
|
||||
L"building a fortification",
|
||||
L"removing a fortification",
|
||||
L"hacking", // TODO.Translate
|
||||
L"%s had to stop %s.",
|
||||
L"The selected barricade cannot be built in this sector", // TODO.Translate
|
||||
};
|
||||
@@ -8961,6 +8962,7 @@ STR16 szBackgroundText_Value[]=
|
||||
L"Nonsmoker",
|
||||
L" %s%d%% enemy CTH if crouched against thick cover in their direction\n",
|
||||
L" %s%d%% building speed\n",
|
||||
L" hacking skill: %s%d ", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szBackgroundTitleText[] = // TODO.Translate
|
||||
@@ -11168,4 +11170,19 @@ STR16 szSMilitiaResourceText[] =
|
||||
L"Not enough resources to train militia!",
|
||||
};
|
||||
|
||||
STR16 szInteractiveActionText[] =
|
||||
{
|
||||
L"%s starts hacking.",
|
||||
L"%s accesses the computer, but finds nothing of interest.",
|
||||
L"%s is not skilled enough to hack the computer.",
|
||||
L"%s reads the file, but learns nothing new.",
|
||||
|
||||
L"%s can't make sense out of this.",
|
||||
L"%s couldn't use the watertap.",
|
||||
L"%s has bought a %s.",
|
||||
L"%s doesn't have enough money. That's just embarassing.",
|
||||
|
||||
L"%s drank from water tap",
|
||||
};
|
||||
|
||||
#endif //ITALIAN
|
||||
|
||||
+18
-1
@@ -8851,7 +8851,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"The enemy refuses to take you as prisoners - they prefer you dead!",
|
||||
L"This behaviour is set OFF in your ini settings.",
|
||||
L"%s has freed %s!",
|
||||
L"A prisoner revealed the location of a high-ranking army officer in %s!", // TODO.Translate
|
||||
L"A high-ranking army officer in %s has been revealed!", // TODO.Translate
|
||||
L"The enemy leader refuses to even consider surrender!",
|
||||
L"%d prisoners volunteered to join our forces.",
|
||||
};
|
||||
@@ -8861,6 +8861,7 @@ STR16 szMTATextStr[]= // TODO.Translate
|
||||
L"nothing",
|
||||
L"building a fortification",
|
||||
L"removing a fortification",
|
||||
L"hacking", // TODO.Translate
|
||||
L"%s had to stop %s.",
|
||||
L"The selected barricade cannot be built in this sector", // TODO.Translate
|
||||
};
|
||||
@@ -8974,6 +8975,7 @@ STR16 szBackgroundText_Value[]=
|
||||
L"Nonsmoker",
|
||||
L" %s%d%% enemy CTH if crouched against thick cover in their direction\n",
|
||||
L" %s%d%% building speed\n",
|
||||
L" hacking skill: %s%d ", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szBackgroundTitleText[] = // TODO.Translate
|
||||
@@ -11181,4 +11183,19 @@ STR16 szSMilitiaResourceText[] =
|
||||
L"Not enough resources to train militia!",
|
||||
};
|
||||
|
||||
STR16 szInteractiveActionText[] =
|
||||
{
|
||||
L"%s starts hacking.",
|
||||
L"%s accesses the computer, but finds nothing of interest.",
|
||||
L"%s is not skilled enough to hack the computer.",
|
||||
L"%s reads the file, but learns nothing new.",
|
||||
|
||||
L"%s can't make sense out of this.",
|
||||
L"%s couldn't use the watertap.",
|
||||
L"%s has bought a %s.",
|
||||
L"%s doesn't have enough money. That's just embarassing.",
|
||||
|
||||
L"%s drank from water tap",
|
||||
};
|
||||
|
||||
#endif //POLISH
|
||||
|
||||
+18
-1
@@ -8830,7 +8830,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"Противник отказывается взять вас в плен - они предпочли бы видеть вас мертвыми!",
|
||||
L"Этот режим отключен в настройках.",
|
||||
L"%s освободил %s!",
|
||||
L"Заключенный указал расположение высокопоставленного офицера в %s!",
|
||||
L"A high-ranking army officer in %s has been revealed!", // TODO.Translate
|
||||
L"Вражеский командир отказывается даже подумать о сдаче!",
|
||||
L"%d заключенных добровольно присоединились к нашим силам.",
|
||||
};
|
||||
@@ -8840,6 +8840,7 @@ STR16 szMTATextStr[]=
|
||||
L"ничего",
|
||||
L"укрепление строится",
|
||||
L"укрепление убирается",
|
||||
L"hacking", // TODO.Translate
|
||||
L"%s был вынужден прекратить %s.",
|
||||
L"Выбранное укрепление не может быть построено в этом секторе",
|
||||
};
|
||||
@@ -8951,6 +8952,7 @@ STR16 szBackgroundText_Value[]=
|
||||
L"Не курит",
|
||||
L" %s%d%% enemy CTH if crouched against thick cover in their direction\n",
|
||||
L" %s%d%% building speed\n",
|
||||
L" hacking skill: %s%d ", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szBackgroundTitleText[] =
|
||||
@@ -11160,4 +11162,19 @@ STR16 szSMilitiaResourceText[] =
|
||||
L"Not enough resources to train militia!",
|
||||
};
|
||||
|
||||
STR16 szInteractiveActionText[] =
|
||||
{
|
||||
L"%s starts hacking.",
|
||||
L"%s accesses the computer, but finds nothing of interest.",
|
||||
L"%s is not skilled enough to hack the computer.",
|
||||
L"%s reads the file, but learns nothing new.",
|
||||
|
||||
L"%s can't make sense out of this.",
|
||||
L"%s couldn't use the watertap.",
|
||||
L"%s has bought a %s.",
|
||||
L"%s doesn't have enough money. That's just embarassing.",
|
||||
|
||||
L"%s drank from water tap",
|
||||
};
|
||||
|
||||
#endif //RUSSIAN
|
||||
|
||||
Reference in New Issue
Block a user