From 8b2d0e33aadd8935d932d106c85da4a226d0f1b2 Mon Sep 17 00:00:00 2001 From: lalien Date: Wed, 19 Apr 2006 17:22:20 +0000 Subject: [PATCH] Data and Source v1.13 Mod High Resolution version from 2006-03-16 ********************************************************* * 2006/03/16 * * RoWa21 * * Developed in VS 2003 * ********************************************************* - Changed missing screens to the High-Resolution - Tactical Screen - Shopkeeper Interface, - Credits Screen, - AutoResolve Screen - ... - Some bugfixing with the screens - Centered message boxes - ... - Merged lalienxx's features (BUT NO BURST AND NO MP3/OGG SUPPORT!) - Rain and lightning visual and sound effects - Visibility radius decrease when rainig - Weapon relyability decrease when rainig - Possibility to spot the enemy at night with lightning - New settings in the ja2.ini file for the rain - Aiming without shooting with "L" key - Move the cursor over an enemy and press the "L" key. - Added judges bugfixing - Swapped internal shopkeeper character numbering to match the Prof.dat in 1.13 (Gabby/Smithy) - Added status of the items to item 'tooltip' - If it is an ammo, the number of available rounds appear - A stack of items now always shows the minimum repair status - No more carrying a stack of grenades into battle only to find most are duds - Made tactical map loading code more robust against maps with bogus buildings - Made tactical map loading code more robust against maps with characters with bogus locations or schedules - Changed the location of the savegame structure - Each mode contains its own savegame folder in its own data-folder - Some general bugfixing - See Bugfixing.xls on the ftp git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@24 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- JA2.suo | Bin 66560 -> 66560 bytes JA2.vcproj | 6 + Laptop/laptop.cpp | 61 +-- NewGameSettings.cpp | 160 ++++++++ NewGameSettings.h | 12 + SaveLoadGame.cpp | 17 + Standard Gaming Platform/sgp.cpp | 9 + Standard Gaming Platform/video.cpp | 32 +- Standard Gaming Platform/video.h | 2 + Strategic/Game Event Hook.cpp | 19 +- Tactical/Handle Items.cpp | 8 +- Tactical/Handle UI.cpp | 62 ++- Tactical/Points.cpp | 18 + Tactical/Rain.cpp | 582 +++++++++++++++++++++++++++++ Tactical/Rain.h | 7 + Tactical/Tactical.vcproj | 6 + Tactical/TeamTurns.cpp | 9 + Tactical/Turn Based Input.cpp | 34 +- Tactical/Weapons.cpp | 32 +- Tactical/opplist.cpp | 41 +- TileEngine/environment.cpp | 321 +++++++++++++++- TileEngine/physics.cpp | 17 +- TileEngine/renderworld.cpp | 9 + gameloop.cpp | 30 ++ local.h | 7 + 25 files changed, 1433 insertions(+), 68 deletions(-) create mode 100644 NewGameSettings.cpp create mode 100644 NewGameSettings.h create mode 100644 Tactical/Rain.cpp create mode 100644 Tactical/Rain.h diff --git a/JA2.suo b/JA2.suo index 7c08a09a89810c54c61b538204c93be49c82cd11..ccabe3bcaf09947c760f7a074d6fac7fc5a4b6e9 100644 GIT binary patch delta 4666 zcmcgwS#VQT7(O=%NlVkDY1*b65K3Fx3Z<+r2trF0uq}la5s5&cAq3MVHeqQ&TXY;5 z^#S;w@Ckjw5r-v@&S)7^6sO>HruaY|lo?@saa=$U6yo=vB&BJ&7xcl~`Et+to&WsX zIk&wB47~>oCy(i;z9NM110BGPL#4&XK5b>JS|)`u*8 zhu&Xte)(BNkCwhSBHf0wis5%fh{!TyuWn%$S{XsHN^HSwkJu{0s8@_@n<*BH7trq) z0gUm9a3q%Yjc#@$iXk+(#By|mFxdxDy{P*{yKtlAL2I?xj-GZ*&ZJnzvP{JSer!fQ zG-xO_vUtmN)NSrIrt5h9$Q^TXstzm;Yh z{Gx~sMh#TazaXVnLWdm{w6WM2sXm)$FdIN?P3)5m83}*gteA_@GGSEfBo+g8`BaNt zP-_r63`lq--=KeKU+384;OE|@|(70cCBA*W^N>3L&iCvv-R4Nk-H%y-n6VwCJDNTDJ z-<#Qj&K$DSjc5*K4ZI|^x`egbz81sg09Ekv3Q-I3S78(NVkx#!B`Q_Ks>Ffqc+}$t)%b_A+ zkBW#TQpBB5>Kcg6d4sb_2bAHFIV6m%A;g15xy7C_qu6F%u?Hoz)t=h1!^Yym(M=Aj79k|D|->ZPly_NXP^QhkWYOVN?DIk;)#Ao zCFf3lRDwPpZag6J(YG%u*d-(s6^4)wUKfiM>IAkcpOYJ$hOb;s1C%aIiN%8o9eun( z*+*xhv#Bq-gknRJDH^TLa3KNtWa0~uWyn)CLRh3tI9Z|IJSN;9w$p9Sbs%lnQzV6YNPmW~Kc1bbg=VTYF*fyeKIH45e^mmF5f$<=_J*^_l ztmG08*M%I3gY`g#WdJkoVyf&*4(FV*Ea)Y15k(YOdwjdV8P@aaBwQ2F#94I2HLa=|^OR za2T{=kv&pLV+>oWOPg(hCuGcGKn3K^RheD$Yt8(V=PegEvxo)%gA(7;?N)ODp}eT)k%si)3zgeg5r5>$b&cM!*RKh z%ww~FO`ASHNx#`TCe4D%d;hS=)~2Z%p_w{{26A#p`d|*esd&Xs5W7=NYu6_KDQQ}( zH(^v}f-X3uD@T%TjyB7+B#Vu|;F6~cpNt{uy}B;duDRM=yHvc_#@-u1?&$z6=h2Sw z_RiC$HY$`gn^Qwww31Up!RYTem&`zkue$Nn4sGg*56C(NEhF-dPR{}1hf-WKM@Mx2 ze_(HfE;!|Eg%jLQ{tsd=&}K&@jmwznBkZ*8dmp)fD5diLQkxSO>wr9!lSz)RJ%hRr z6?u=srBMBHpcC^{vS-;NoyYL)O{u<(Zzc8R@D)o}Y8z7z0#h>a_g>vFYyN_iB#1k> zHd`VI+8YsfobBWPli=IZ9;&+NGt8Yge*twoQ}X{UNj;a1feo9 gi35;&hYE1Jj|W@UKKa>&kV0tT1MqG{DUT`t0GUJn!~g&Q literal 66560 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 ASpWb4 diff --git a/JA2.vcproj b/JA2.vcproj index 65a9edae6..5de4515df 100644 --- a/JA2.vcproj +++ b/JA2.vcproj @@ -1980,6 +1980,9 @@ BrowseInformation="1"/> + + + + diff --git a/Laptop/laptop.cpp b/Laptop/laptop.cpp index 924154f9f..41f75a303 100644 --- a/Laptop/laptop.cpp +++ b/Laptop/laptop.cpp @@ -353,8 +353,11 @@ static BOOLEAN fNewWWW=TRUE; extern UINT32 guiRainLoop; +// WANNE 2 INT32 giRainDelayInternetSite=-1; + + // have we visitied this site already? //BOOLEAN fVisitedBookmarkAlready[20]; @@ -850,15 +853,16 @@ INT32 EnterLaptop() // Stop ambients... StopAmbients( ); - //if its raining, start the rain showers - if( IsItRaining() ) - { - //Enable the rain delay warning - giRainDelayInternetSite = -1; + // WANNE 2: disabled rain sound when laptop is displayed + ////if its raining, start the rain showers + //if( IsItRaining() ) + //{ + // //Enable the rain delay warning + // giRainDelayInternetSite = -1; - //lower the volume - guiRainLoop = PlayJA2Ambient( RAIN_1, LOWVOLUME, 0 ); - } + // //lower the volume + // guiRainLoop = PlayJA2Ambient( RAIN_1, LOWVOLUME, 0 ); + //} //open the laptop library @@ -1013,12 +1017,13 @@ void ExitLaptop() // Start ambients... BuildDayAmbientSounds( ); + // WANNE 2: disabled rain sound when laptop is displayed //if its raining, start the rain showers - if( IsItRaining() ) - { - //Raise the volume to where it was - guiRainLoop = PlayJA2Ambient( RAIN_1, MIDVOLUME, 0 ); - } + //if( IsItRaining() ) + //{ + // //Raise the volume to where it was + // guiRainLoop = PlayJA2Ambient( RAIN_1, MIDVOLUME, 0 ); + //} // release cursor FreeMouseCursor( ); @@ -3556,18 +3561,19 @@ void BookmarkCallBack(MOUSE_REGION * pRegion, INT32 iReason ) void GoToWebPage(INT32 iPageId ) { - //if it is raining, popup a warning first saying connection time may be slow - if( IsItRaining() ) - { - if( giRainDelayInternetSite == -1 ) - { - DoLapTopMessageBox( MSG_BOX_LAPTOP_DEFAULT, pErrorStrings[4], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, InternetRainDelayMessageBoxCallBack ); - giRainDelayInternetSite = iPageId; - return; - } - } - else - giRainDelayInternetSite = -1; + // WANNE 2: disabled rain sound when laptop is displayed + ////if it is raining, popup a warning first saying connection time may be slow + //if( IsItRaining() ) + //{ + // if( giRainDelayInternetSite == -1 ) + // { + // DoLapTopMessageBox( MSG_BOX_LAPTOP_DEFAULT, pErrorStrings[4], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, InternetRainDelayMessageBoxCallBack ); + // giRainDelayInternetSite = iPageId; + // return; + // } + //} + //else + // giRainDelayInternetSite = -1; switch(iPageId) { @@ -6347,10 +6353,11 @@ BOOLEAN IsItRaining() void InternetRainDelayMessageBoxCallBack( UINT8 bExitValue ) { - GoToWebPage( giRainDelayInternetSite ); + // WANNE 2 + //GoToWebPage( giRainDelayInternetSite ); //Set to -2 so we dont due the message for this occurence of laptop - giRainDelayInternetSite = -2; + //giRainDelayInternetSite = -2; } diff --git a/NewGameSettings.cpp b/NewGameSettings.cpp new file mode 100644 index 000000000..238f4625c --- /dev/null +++ b/NewGameSettings.cpp @@ -0,0 +1,160 @@ +#include "types.h" +#include "NewGameSettings.h" +#include "FileMan.h" + +#include +#include + +#define GAME_INI_FILE "\\Ja2.ini" + +BOOLEAN gfStretch = FALSE; +BOOLEAN gfStretchWinGDI = FALSE; +BOOLEAN gfVSync = FALSE; + +BOOLEAN gfAllowRain = FALSE; + +UINT16 gusRainChancePerDay = 100, gusRainMinLength = 60, gusRainMaxLength = 180; + +extern UINT32 guiMinLightningInterval; +extern UINT32 guiMaxLightningInterval; +extern UINT32 guiMinDLInterval; +extern UINT32 guiMaxDLInterval; +extern UINT32 guiProlongLightningIfSeenSomeone; +extern UINT32 guiChanceToDoLightningBetweenTurns; + +extern UINT32 guiMaxRainDrops; + +typedef struct +{ + CHAR8* strParamName; + CHAR8* strSectionName; + LPVOID pVar; + UINT8 ubVarType; +}TSetting; + +#define SET_RAIN "JA2 Rain Settings" +#define SET_THUNDER "JA2 Thunder Settings" + +enum +{ + VT_UINT32, + VT_UINT16, + VT_UINT8, + VT_INT32, + VT_INT16, + VT_INT8, + VT_BOOLEAN +}; + +TSetting gpSettings[] = { + + // Rain settings + {"ALLOW_RAIN", SET_RAIN, &gfAllowRain, VT_BOOLEAN}, + {"RAIN_CHANCE_PER_DAY", SET_RAIN, &gusRainChancePerDay, VT_UINT16}, + {"RAIN_MIN_LENGTH_IN_MINUTES", SET_RAIN, &gusRainMinLength, VT_UINT16}, + {"RAIN_MAX_LENGTH_IN_MINUTES", SET_RAIN, &gusRainMaxLength, VT_UINT16}, + {"MAX_RAIN_DROPS", SET_RAIN, &guiMaxRainDrops, VT_UINT32}, + + // Thunder settings + {"MIN_INTERVAL_BETWEEN_LIGHTNINGS_IN_REAL_TIME_SECONDS", SET_THUNDER, &guiMinLightningInterval, VT_UINT32}, + {"MAX_INTERVAL_BETWEEN_LIGHTNINGS_IN_REAL_TIME_SECONDS", SET_THUNDER, &guiMaxLightningInterval, VT_UINT32}, + {"MIN_INTERVAL_BETWEEN_LIGHTNING_AND_THUNDERCLAPS_IN_SECONDS", SET_THUNDER, &guiMinDLInterval, VT_UINT32}, + {"MAX_INTERVAL_BETWEEN_LIGHTNING_AND_THUNDERCLAPS_IN_SECONDS", SET_THUNDER, &guiMaxDLInterval, VT_UINT32}, + {"PROLOGNE_DELAY_IF_SEEN_SOMEONE_DURING_LIGHTNING_IN_TURNBASED_IN_SECONDS", SET_THUNDER, &guiProlongLightningIfSeenSomeone, VT_UINT32}, + {"CHANCE_TO_DO_LIGHTNING_BETWEEN_TURNS", SET_THUNDER, &guiChanceToDoLightningBetweenTurns, VT_UINT32}, + + {0,0,0,VT_UINT8} +}; + + +void NSSaveSettings() +{ + CHAR8 zStr[ 256 ]; + TSetting* pCurr = gpSettings; + INT32 iBuf; + BOOLEAN fFileCreated = !FileExists( GAME_INI_FILE ); + + FileDelete( GAME_INI_FILE ); + + while( pCurr->pVar ) + { + switch( pCurr->ubVarType ) + { + case VT_UINT32: + iBuf = *((UINT32*)pCurr->pVar); + break; + case VT_UINT16: + iBuf = *((UINT16*)pCurr->pVar); + break; + case VT_UINT8: + iBuf = *((UINT8*)pCurr->pVar); + break; + case VT_INT32: + iBuf = *((INT32*)pCurr->pVar); + break; + case VT_INT16: + iBuf = *((INT16*)pCurr->pVar); + break; + case VT_INT8: + iBuf = *((INT8*)pCurr->pVar); + break; + case VT_BOOLEAN: + iBuf = *((BOOLEAN*)pCurr->pVar); + break; + } + + sprintf( zStr, "%d", iBuf ); + + WritePrivateProfileString( pCurr->strSectionName, pCurr->strParamName, zStr, GAME_INI_FILE ); + + ++pCurr; + } +} + +void NSLoadSettings() +{ + CHAR8 zStr[ 256 ]; + UINT32 uiRetVal=0; + TSetting* pCurr = gpSettings; + INT32 iBuf; + STRING512 INIFile; // Path to the ini file + + // Get Executable Directory + GetExecutableDirectory( INIFile ); + + strcat(INIFile, "\\Ja2.ini"); + + while( pCurr->pVar ) + { + uiRetVal = GetPrivateProfileString( pCurr->strSectionName, pCurr->strParamName, "", zStr, 256, INIFile ); + if( uiRetVal && strlen( zStr ) ) + { + sscanf( zStr, "%d", &iBuf ); + switch( pCurr->ubVarType ) + { + case VT_UINT32: + *((UINT32*)pCurr->pVar) = iBuf; + break; + case VT_UINT16: + *((UINT16*)pCurr->pVar) = iBuf; + break; + case VT_UINT8: + *((UINT8*)pCurr->pVar) = iBuf; + break; + case VT_INT32: + *((INT32*)pCurr->pVar) = iBuf; + break; + case VT_INT16: + *((INT16*)pCurr->pVar) = iBuf; + break; + case VT_INT8: + *((INT8*)pCurr->pVar) = iBuf; + break; + case VT_BOOLEAN: + *((BOOLEAN*)pCurr->pVar) = iBuf; + break; + } + } + pCurr++; + } +} \ No newline at end of file diff --git a/NewGameSettings.h b/NewGameSettings.h new file mode 100644 index 000000000..e8845b597 --- /dev/null +++ b/NewGameSettings.h @@ -0,0 +1,12 @@ +#ifndef ___NEW_GAME_SETTINGS___ +#define ___NEW_GAME_SETTINGS___ + +extern BOOLEAN gfUseABResources; +extern BOOLEAN gfEnableEmergencyButton_SkipStrategicEvents; +extern UINT32 guiMaxTossSearchDist; +extern BOOLEAN gfShowItemShadow; + +void NSSaveSettings(); +void NSLoadSettings(); + +#endif \ No newline at end of file diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index f55ece0bf..e9501312d 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -101,6 +101,11 @@ #include "Enemy Soldier Save.h" #include "BobbyRMailOrder.h" #include "Mercs.h" +#include "INIReader.h" + +//rain +#include "Rain.h" +//end rain ///////////////////////////////////////////////////// // @@ -4538,6 +4543,10 @@ BOOLEAN SaveGeneralInfo( HWFILE hFile ) return( TRUE ); } +//rain +extern UINT32 guiRainLoop; +//end rain + BOOLEAN LoadGeneralInfo( HWFILE hFile ) { @@ -4617,6 +4626,14 @@ BOOLEAN LoadGeneralInfo( HWFILE hFile ) //The current state of the weather guiEnvWeather = sGeneralInfo.uiEnvWeather; + //rain + if ( guiRainLoop != NO_SAMPLE ) + { + SoundStop( guiRainLoop ); + guiRainLoop = NO_SAMPLE; + } + //end rain + gubDefaultButton = sGeneralInfo.ubDefaultButton; gfSkyriderEmptyHelpGiven = sGeneralInfo.fSkyriderEmptyHelpGiven; diff --git a/Standard Gaming Platform/sgp.cpp b/Standard Gaming Platform/sgp.cpp index a8ba30135..989e692c7 100644 --- a/Standard Gaming Platform/sgp.cpp +++ b/Standard Gaming Platform/sgp.cpp @@ -705,6 +705,15 @@ int PASCAL HandledWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR p return( 0 ); } + //rain + NSLoadSettings(); + //NSSaveSettings(); + //InitResolution(); + + //EmergencyExitButtonInit(); + //end rain + + ghInstance = hInstance; // Copy commandline! diff --git a/Standard Gaming Platform/video.cpp b/Standard Gaming Platform/video.cpp index 2e6c1a73e..251b16ace 100644 --- a/Standard Gaming Platform/video.cpp +++ b/Standard Gaming Platform/video.cpp @@ -772,7 +772,6 @@ BOOLEAN CanBlitToMouseBuffer(void) void InvalidateRegion(INT32 iLeft, INT32 iTop, INT32 iRight, INT32 iBottom) { - // WANNE 2 if (gfForceFullScreenRefresh == TRUE) { // @@ -1504,6 +1503,12 @@ void ScrollJA2Background(UINT32 uiDirection, INT16 sScrollXIncrement, INT16 sScr } +//rain +BOOLEAN IsItAllowedToRenderRain(); +extern UINT32 guiRainRenderSurface; + +BOOLEAN gfNextRefreshFullScreen = FALSE; +//end rain void RefreshScreen(void *DummyVariable) { @@ -1523,6 +1528,17 @@ void RefreshScreen(void *DummyVariable) fShowMouse = FALSE; } + if( gfNextRefreshFullScreen ) + { + if( guiCurrentScreen == GAME_SCREEN ) + { + InvalidateScreen(); + gfRenderScroll = FALSE; + // gfForceFullScreenRefresh = TRUE; + // guiFrameBufferState == BUFFER_DIRTY; + } + gfNextRefreshFullScreen = FALSE; + } //DebugMsg(TOPIC_VIDEO, DBG_LEVEL_0, "Looping in refresh"); @@ -2102,6 +2118,20 @@ void RefreshScreen(void *DummyVariable) } + + + /////////////////////////////////////////////////////////////////////////////////////////////// + // Rain // + /////////////////////////////////////////////////////////////////////////////////////////////// + + if( IsItAllowedToRenderRain() && gfProgramIsRunning ) + { + BltVideoSurface( BACKBUFFER, guiRainRenderSurface, 0, 0, 0, VS_BLT_FAST | VS_BLT_USECOLORKEY, NULL ); + gfNextRefreshFullScreen = TRUE; + } + + + /////////////////////////////////////////////////////////////////////////////////////////////// // // (1) Flip Pages diff --git a/Standard Gaming Platform/video.h b/Standard Gaming Platform/video.h index 16a01525d..c7cd4e00c 100644 --- a/Standard Gaming Platform/video.h +++ b/Standard Gaming Platform/video.h @@ -66,6 +66,8 @@ extern void StartFrameBufferRender(void); extern void EndFrameBufferRender(void); extern void PrintScreen(void); + + extern BOOLEAN EraseMouseCursor( ); extern BOOLEAN SetMouseCursorProperties( INT16 sOffsetX, INT16 sOffsetY, UINT16 usCursorHeight, UINT16 usCursorWidth ); extern BOOLEAN BltToMouseCursor(UINT32 uiVideoObjectHandle, UINT16 usVideoObjectSubIndex, UINT16 usXPos, UINT16 usYPos ); diff --git a/Strategic/Game Event Hook.cpp b/Strategic/Game Event Hook.cpp index 64f7975a2..fe6c1aaed 100644 --- a/Strategic/Game Event Hook.cpp +++ b/Strategic/Game Event Hook.cpp @@ -297,15 +297,16 @@ BOOLEAN ExecuteStrategicEvent( STRATEGICEVENT *pEvent ) case EVENT_RAINSTORM: // ATE: Disabled - // - //if( pEvent->ubEventType == ENDRANGED_EVENT ) - //{ - // EnvEndRainStorm( ); - //} - //else - //{ - // EnvBeginRainStorm( (UINT8)pEvent->uiParam ); - //} + //rain + if( pEvent->ubEventType == ENDRANGED_EVENT ) + { + EnvEndRainStorm( ); + } + else + { + EnvBeginRainStorm( (UINT8)pEvent->uiParam ); + } + //end rain break; case EVENT_MAKE_CIV_GROUP_HOSTILE_ON_NEXT_SECTOR_ENTRANCE: diff --git a/Tactical/Handle Items.cpp b/Tactical/Handle Items.cpp index 242f48961..95d832241 100644 --- a/Tactical/Handle Items.cpp +++ b/Tactical/Handle Items.cpp @@ -402,14 +402,14 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, UINT16 usGridNo, INT8 bLevel, UINT16 us pSoldier->fDontChargeTurningAPs = TRUE; } } - else + /*else { // If raising gun, don't charge turning! if ( fAddingTurningCost ) { pSoldier->fDontChargeReadyAPs = TRUE; } - } + }*/ @@ -1301,14 +1301,14 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, UINT16 usGridNo, INT8 bLevel, UINT16 us pSoldier->fDontChargeTurningAPs = TRUE; } } - else + /*else { // If raising gun, don't charge turning! if ( fAddingTurningCost ) { pSoldier->fDontChargeReadyAPs = TRUE; } - } + }*/ } // If this is a player guy, show message about no APS diff --git a/Tactical/Handle UI.cpp b/Tactical/Handle UI.cpp index afbba3c54..f581ebe83 100644 --- a/Tactical/Handle UI.cpp +++ b/Tactical/Handle UI.cpp @@ -75,6 +75,13 @@ #endif +//extern BOOLEAN gfDisplayFullCountRingBurst; +extern UINT16 PickSoldierReadyAnimation( SOLDIERTYPE *pSoldier, BOOLEAN fEndReady ); + +//#define AP_TO_AIM_TILE_IF_GETTING_READY 1 +#define AP_TO_AIM_TILE_IF_ALREADY_READY ( Weapon[ Item[pSoldier->inv[HANDPOS].usItem].ubClassIndex ].ubReadyTime ? 2 : 1 ) +#define AP_TO_AIM_TILE_IF_GETTING_READY AP_TO_AIM_TILE_IF_ALREADY_READY + #define MAX_ON_DUTY_SOLDIERS 6 ///////////////////////////////////////////////////////////////////////////////////// @@ -4476,11 +4483,13 @@ void SetConfirmMovementModeCursor( SOLDIERTYPE *pSoldier, BOOLEAN fFromMove ) } +UINT8 gubShowActionPointsInRed = 0; UINT32 UIHandleLCOnTerrain( UI_EVENT *pUIEvent ) { SOLDIERTYPE *pSoldier; INT16 sFacingDir, sXPos, sYPos; + UINT16 usAnimState; guiNewUICursor = LOOK_UICURSOR; @@ -4511,10 +4520,26 @@ UINT32 UIHandleLCOnTerrain( UI_EVENT *pUIEvent ) if ( sFacingDir != pSoldier->bDirection ) { gsCurrentActionPoints = GetAPsToLook( pSoldier ); + gfUIHandleShowMoveGrid = FALSE; } else { + usAnimState = PickSoldierReadyAnimation( pSoldier, FALSE ); + + if( usAnimState != INVALID_ANIMATION ) + { + gsCurrentActionPoints = GetAPsToReadyWeapon( pSoldier, usAnimState ) + AP_TO_AIM_TILE_IF_GETTING_READY; + } + else if( pSoldier->sLastTarget != sXPos + (MAXCOL * sYPos ) ) + gsCurrentActionPoints = AP_TO_AIM_TILE_IF_ALREADY_READY; + else gsCurrentActionPoints = 0; + + gfUIHandleShowMoveGrid = TRUE; + gsUIHandleShowMoveGridLocation = sXPos + (MAXCOL * sYPos ); + + gubShowActionPointsInRed = 5; + //gfDisplayFullCountRingBurst = FALSE; } // Determine if we can afford! @@ -4538,7 +4563,8 @@ UINT32 UIHandleLCChangeToLook( UI_EVENT *pUIEvent ) BOOLEAN MakeSoldierTurn( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos ) { - INT16 sFacingDir, sAPCost; + INT16 sFacingDir, sAPCost, sAPCostToReady; + UINT16 usAnimState; // Get direction from mouse pos sFacingDir = GetDirectionFromXY( sXPos, sYPos, pSoldier ); @@ -4569,8 +4595,42 @@ BOOLEAN MakeSoldierTurn( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos ) return( TRUE ); } + else + { + usAnimState = PickSoldierReadyAnimation( pSoldier, FALSE ); + sAPCostToReady = 0; + + if( usAnimState != INVALID_ANIMATION ) + { + sAPCostToReady = GetAPsToReadyWeapon( pSoldier, usAnimState ); + sAPCost = sAPCostToReady + AP_TO_AIM_TILE_IF_GETTING_READY; + } + else if( pSoldier->sLastTarget != sXPos + (MAXCOL * sYPos ) ) + sAPCost = AP_TO_AIM_TILE_IF_ALREADY_READY; + else + return FALSE; + + + // Check AP cost... + if ( !EnoughPoints( pSoldier, sAPCost, 0, TRUE ) ) + { return( FALSE ); + } + + if( usAnimState != INVALID_ANIMATION ) + SoldierReadyWeapon( pSoldier, sXPos, sYPos, FALSE ); + + pSoldier->bTurningFromUI = TRUE; + guiOldEvent = LA_BEGINUIOURTURNLOCK; + + // Setting "Last Target" + + pSoldier->sLastTarget = sXPos + (MAXCOL * sYPos); + DeductPoints( pSoldier, (INT16)(sAPCost - sAPCostToReady), 0 ); + + return( TRUE ); + } } diff --git a/Tactical/Points.cpp b/Tactical/Points.cpp index 3cd0fbcdf..23629d591 100644 --- a/Tactical/Points.cpp +++ b/Tactical/Points.cpp @@ -26,6 +26,10 @@ #include "Soldier Profile.h" #endif +//rain +#define BREATH_GAIN_REDUCTION_PER_RAIN_INTENSITY 25 +//end rain + extern BOOLEAN IsValidSecondHandShot( SOLDIERTYPE *pSoldier ); @@ -770,6 +774,10 @@ void UnusedAPsToBreath(SOLDIERTYPE *pSold) } +//rain +extern INT8 gbCurrentRainIntensity; +//end rain + INT16 GetBreathPerAP( SOLDIERTYPE *pSoldier, UINT16 usAnimState ) { INT16 sBreathPerAP = 0; @@ -844,6 +852,14 @@ INT16 GetBreathPerAP( SOLDIERTYPE *pSoldier, UINT16 usAnimState ) DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Unknown end-of-turn breath anim: %s", gAnimControl[ usAnimState ].zAnimStr ) ); } + //rain + // Reduce breath gain on 25%/rain intensity + if( sBreathPerAP < 0 && ( pSoldier->bLevel ||!FindStructure( pSoldier->sGridNo, STRUCTURE_ROOF ) ) && pSoldier->bBreath > 1) + { + sBreathPerAP -= sBreathPerAP * gbCurrentRainIntensity * BREATH_GAIN_REDUCTION_PER_RAIN_INTENSITY / 100 ; + } + //end rain + return( sBreathPerAP ); } @@ -1296,6 +1312,8 @@ UINT8 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubAddTurni // bFullAPs are BASE APs, which do not include APs caried over from the previous turn. bFullAPs = CalcActionPoints( pSoldier ); + //bFullAPs = pSoldier->bInitialActionPoints;//CalcActionPoints( pSoldier ); //lal + // aim skill is the same whether we are using 1 or 2 guns bAimSkill = CalcAimSkill( pSoldier, usItem ); diff --git a/Tactical/Rain.cpp b/Tactical/Rain.cpp new file mode 100644 index 000000000..7d7bec463 --- /dev/null +++ b/Tactical/Rain.cpp @@ -0,0 +1,582 @@ +// WANNE 2 +#ifdef PRECOMPILEDHEADERS + #include "Tactical All.h" +#else + #include "types.h" + #include "soldier control.h" + #include "overhead.h" + #include "animation control.h" + #include "points.h" + #include "opplist.h" + #include "timer.h" + #include "event pump.h" + #include "Sound Control.h" + #include "interface.h" + #include "Isometric Utils.h" + #include "Font Control.H" + #include "ai.h" + #include "interface.h" + #include "message.h" + #include "text.h" + #include "TeamTurns.h" + #include "Smell.h" + #include "game clock.h" + #include "Soldier Functions.h" + #include "cursors.h" + #include "Queen Command.h" + #include "Pathai.h" + #include "Music Control.h" + #include "Strategic Turns.h" + #include "lighting.h" + #include "environment.h" + #include "Explosion Control.h" + #include "dialogue control.h" + #include "Soldier Profile Type.h" + #include "SmokeEffects.h" + #include "lighteffects.h" + #include "air raid.h" + #include "meanwhile.h" + #include "SkillCheck.h" + #include "AIInternals.h" + #include "AIList.h" + #ifdef DEBUG_INTERRUPTS + #include "debug.h" + #endif +#endif + +#include "Rain.h" + +// WANNE 2 +// Shop Keeper Interface +#define SKI_X_OFFSET (((SCREEN_WIDTH - 536) / 2)) +#define SKI_Y_OFFSET ((((SCREEN_HEIGHT - 140) - 340) / 2)) + +// WANNE 2 +// Overhead Map +#define OM_X_OFFSET 0 +#define OM_Y_OFFSET 0 + + + + +#define RAIN_UPDATE_RATE 60 +#define PERCENT_OF_DROPS_GOING_TO_THE_EDGE_OF_SCREEN 0.25f + +#define DROP_ANGLE_CHANGE_RATE 1.0f + +#define MIN_DROP_LENGTH 2.0f +#define ADD_DROP_LENGTH_IF_STORM 2.0f +#define DROP_LENGTH_RANGE 2.0f +#define DROP_LENGTH_CHANGE_RATE 0.1f +#define DROP_LENGTH_RAND 2.0f + +#define BASE_DROP_SPEED 7.0f +#define DROP_SPEED_RANGE 3.5f +#define DROP_SPEED_CHANGE_RATE 0.1f +#define DROP_SPEED_RAND 5.0f + +UINT32 guiMaxRainDrops = 79; + +#define RESOLUTION_FACTOR_ON_MAXIMUM_DROPS ((FLOAT) ( SCREEN_WIDTH * SCREEN_HEIGHT ) / ((FLOAT) 640 * 480 ) ) +#define BASE_MAXIMUM_DROPS guiMaxRainDrops * RESOLUTION_FACTOR_ON_MAXIMUM_DROPS + +#define DEGREE(a) ( 3.14159 / 180 * a ) + +typedef struct +{ + BOOLEAN fAlive; + + FLOAT fpX; + FLOAT fpY; + FLOAT fpIncrX; + FLOAT fpIncrY; + + FLOAT fpEndRelX; + FLOAT fpEndRelY; + + UINT32 uiAmountOfTicksToLive; +}TRainDrop; + + +static BOOLEAN fFirstTime = TRUE; +UINT32 guiRainRenderSurface = 0; +UINT32 guiLastRainUpdate = 0; +RECT gRainRegion; + +TRainDrop *pRainDrops = 0; +UINT32 guiCurrMaxAmountOfRainDrops = 0; +UINT32 guiCurrAmountOfDeadRainDrops = 0; + +INT8 gbCurrentRainIntensity = 0; + +FLOAT fpCurrDropAngleOfFalling = 0; +FLOAT fpCurrDropLength = 0; +FLOAT fpCurrDropSpeed = 0; + +FLOAT fpMaxDropAngleOfFalling = 0; +FLOAT fpMaxDropLength = 0; +FLOAT fpMaxDropSpeed = 0; + +FLOAT fpMinDropAngleOfFalling = 0; +FLOAT fpMinDropLength = 0; +FLOAT fpMinDropSpeed = 0; + + +extern UINT32 guiCurrentScreen; +extern BOOLEAN gfAllowRain; + +extern INT16 gsVIEWPORT_WINDOW_END_Y; +extern INT16 gsVIEWPORT_WINDOW_START_Y; + +#define VIDEO_OVERLAYS 100 +extern VIDEO_OVERLAY gVideoOverlays[ VIDEO_OVERLAYS ]; +extern UINT32 guiNumVideoOverlays; + +extern MercPopUpBox *gPopUpTextBox; + +INT8 GetRainIntensityFromEnvWeather() +{ + INT8 bRes = 0; + + // Debug!!! +// guiEnvWeather |= WEATHER_FORECAST_THUNDERSHOWERS; + + if( guiEnvWeather & WEATHER_FORECAST_SHOWERS ) bRes += 1; + if( guiEnvWeather & WEATHER_FORECAST_THUNDERSHOWERS ) bRes += 2; + + return bRes; +} + +BOOLEAN IsItAllowedToRenderRain() +{ + if( !gfAllowRain )return FALSE; + + if( !( guiEnvWeather & WEATHER_FORECAST_THUNDERSHOWERS | WEATHER_FORECAST_SHOWERS ) )return FALSE; + + if( guiCurrentScreen != GAME_SCREEN && guiCurrentScreen != SHOPKEEPER_SCREEN ) return FALSE; + + return TRUE; +} + +void InitializeRainVideoObject( ) +{ + VSURFACE_DESC vs_desc; + UINT16 usWidth; + UINT16 usHeight; + UINT8 ubBitDepth; + + // Create render buffer + GetCurrentVideoSettings( &usWidth, &usHeight, &ubBitDepth ); + vs_desc.fCreateFlags = VSURFACE_CREATE_DEFAULT | VSURFACE_SYSTEM_MEM_USAGE; + vs_desc.usWidth = usWidth; + vs_desc.usHeight = usHeight; + vs_desc.ubBitDepth = ubBitDepth; + + AddVideoSurface( &vs_desc, &guiRainRenderSurface ); +} + +void InitializeRainData() +{ + InitializeRainVideoObject(); + + gRainRegion.left = 0; + gRainRegion.top = 0; + gRainRegion.right = SCREEN_WIDTH; + gRainRegion.bottom = SCREEN_HEIGHT - 120; +} + +void ResetRain() +{ + if( pRainDrops ) + { + MemFree( pRainDrops ); + pRainDrops = NULL; + } + + guiCurrMaxAmountOfRainDrops = 0; +} + +void GenerateRainDropsList() +{ + guiCurrMaxAmountOfRainDrops = (UINT32)BASE_MAXIMUM_DROPS * gbCurrentRainIntensity; + + pRainDrops = (TRainDrop *)MemAlloc( sizeof( TRainDrop ) * guiCurrMaxAmountOfRainDrops ); + memset( pRainDrops, 0, sizeof( TRainDrop ) * guiCurrMaxAmountOfRainDrops ); +} + +void KillOutOfRegionRainDrops() +{ + UINT32 uiIndex; + + for( uiIndex = 0; uiIndex < guiCurrMaxAmountOfRainDrops; ++uiIndex ) + { + TRainDrop *pCurr = &pRainDrops[ uiIndex ]; + + if( ( pCurr->fpX < gRainRegion.left || pCurr->fpX >= gRainRegion.right || + pCurr->fpY < gRainRegion.top || pCurr->fpY >= gRainRegion.bottom ) && + ( pCurr->fpX + pCurr->fpEndRelX < gRainRegion.left || pCurr->fpX + pCurr->fpEndRelX >= gRainRegion.right || + pCurr->fpY + pCurr->fpEndRelY < gRainRegion.top || pCurr->fpY + pCurr->fpEndRelY >= gRainRegion.bottom ) ) + { + pCurr->fAlive = FALSE; + guiCurrAmountOfDeadRainDrops++; + } + + } +} + +void CreateRainDrops() +{ + UINT32 uiIndex; + UINT32 uiCreatedDrops = 0; + FLOAT fpCos, fpSin, fpAbsTg; + FLOAT fpDropLength = fpCurrDropLength; + FLOAT fpDropSpeed = fpCurrDropSpeed; + FLOAT fpNumDropsToXBorder = 0; + BOOLEAN fLoopIsDone; + UINT32 uiIndRand; + + fpCos = cos( DEGREE(fpCurrDropAngleOfFalling) ); + fpSin = sin( DEGREE(fpCurrDropAngleOfFalling) ); + + if( fpCos ) + fpAbsTg = fabs( fpSin / fpCos ); // take only absolute valuse + else + fpAbsTg = 0; // well, it can't really be ;) + + for( uiIndex = 0; uiIndex < guiCurrMaxAmountOfRainDrops; ++uiIndex ) + { + TRainDrop *pCurr = &pRainDrops[ uiIndex ]; + + if( pCurr->fAlive )continue; + + uiIndRand = (((UINT32)pCurr) / sizeof(TRainDrop) ) % 20; + + fpDropLength = fpCurrDropLength + ( (((UINT32)pCurr) / sizeof(TRainDrop) ) % 7 ) * DROP_LENGTH_RAND / 6; + fpDropSpeed = fpCurrDropSpeed + ( ( ((UINT32)pCurr) / sizeof(TRainDrop) + 43 ) % 13 ) * DROP_SPEED_RAND / 12; + + pCurr->fAlive = TRUE; + + pCurr->fpIncrX = fpCos * fpDropSpeed; + pCurr->fpIncrY = fpSin * fpDropSpeed; + + pCurr->fpEndRelX = -fpCos * fpDropLength; + pCurr->fpEndRelY = -fpSin * fpDropLength; + + // where we want the drops to fall + + if( uiIndex < guiCurrMaxAmountOfRainDrops * PERCENT_OF_DROPS_GOING_TO_THE_EDGE_OF_SCREEN ) + { + if( !fpCos ) + fpNumDropsToXBorder = 0; + else + { + if( fpAbsTg < 1 ) + { + fpNumDropsToXBorder = 1.0f - fpAbsTg; + fpNumDropsToXBorder *= (((FLOAT)SCREEN_HEIGHT - 120) / (FLOAT)SCREEN_WIDTH); + fpNumDropsToXBorder *= guiCurrMaxAmountOfRainDrops * PERCENT_OF_DROPS_GOING_TO_THE_EDGE_OF_SCREEN / 2; + + fpNumDropsToXBorder += guiCurrMaxAmountOfRainDrops * PERCENT_OF_DROPS_GOING_TO_THE_EDGE_OF_SCREEN / 2; + } + else + { + fpNumDropsToXBorder = 1 / fpAbsTg; + fpNumDropsToXBorder *= (((FLOAT)SCREEN_HEIGHT - 120) / (FLOAT)SCREEN_WIDTH); + fpNumDropsToXBorder *= guiCurrMaxAmountOfRainDrops * PERCENT_OF_DROPS_GOING_TO_THE_EDGE_OF_SCREEN / 2; + } + } + + if( uiIndex >= fpNumDropsToXBorder ) + { + pCurr->fpX = gRainRegion.left + Random( gRainRegion.right - gRainRegion.left ); + pCurr->fpY = gRainRegion.bottom - 1; + } + else if( fpCos > 0 ) + { + pCurr->fpX = gRainRegion.right - 1; + pCurr->fpY = gRainRegion.top + Random( gRainRegion.bottom - gRainRegion.top ); + }else{ + pCurr->fpX = 0; + pCurr->fpY = gRainRegion.top + Random( gRainRegion.bottom - gRainRegion.top ); + } + }else{ + pCurr->fpX = gRainRegion.left + Random( gRainRegion.right - gRainRegion.left ); + pCurr->fpY = gRainRegion.top + Random( gRainRegion.bottom - gRainRegion.top ); + } + + pCurr->uiAmountOfTicksToLive = 0; + fLoopIsDone = FALSE; + + while( !fLoopIsDone ) + { + pCurr->fpX -= pCurr->fpIncrX; + pCurr->fpY -= pCurr->fpIncrY; + pCurr->uiAmountOfTicksToLive++; + + if( pCurr->fpX >= gRainRegion.right - 1 ) + { + pCurr->fpX = gRainRegion.right - 1 - uiIndRand * pCurr->fpIncrX / 20 ; + fLoopIsDone = TRUE; + } + if( pCurr->fpX < gRainRegion.left ) + { + pCurr->fpX = gRainRegion.left - uiIndRand * pCurr->fpIncrX / 20 ; + fLoopIsDone = TRUE; + } + if( pCurr->fpY >= gRainRegion.bottom - 1 ) + { + pCurr->fpY = gRainRegion.bottom - 1 - uiIndRand * pCurr->fpIncrX / 20 ; + fLoopIsDone = TRUE; + } + if( pCurr->fpY < gRainRegion.top ) + { + pCurr->fpY = gRainRegion.top - uiIndRand * pCurr->fpIncrX / 20 ; + fLoopIsDone = TRUE; + } + } + + uiCreatedDrops++; + + // drop creation is done!!! + + } +} + +void UpdateRainDrops() +{ + UINT32 uiIndex; + + for( uiIndex = 0; uiIndex < guiCurrMaxAmountOfRainDrops; ++uiIndex ) + { + TRainDrop *pCurr = &pRainDrops[ uiIndex ]; + + if( !pCurr->fAlive )continue; + + if( pCurr->uiAmountOfTicksToLive ) + { + pCurr->fpX += pCurr->fpIncrX; + pCurr->fpY += pCurr->fpIncrY; + pCurr->uiAmountOfTicksToLive--; + }else{ + pCurr->fpEndRelX += pCurr->fpIncrX; + pCurr->fpEndRelY += pCurr->fpIncrY; + + if( ( pCurr->fpEndRelX > 0 && pCurr->fpIncrX > 0 ) || + ( pCurr->fpEndRelX < 0 && pCurr->fpIncrX < 0 ) || + ( pCurr->fpEndRelY > 0 && pCurr->fpIncrY > 0 ) || + ( pCurr->fpEndRelY < 0 && pCurr->fpIncrY < 0 ) ) + { + pCurr->fAlive = FALSE; + guiCurrAmountOfDeadRainDrops++; + } + } + } + +} + +void BlankRainRenderSurface() +{ + ColorFillVideoSurfaceArea( guiRainRenderSurface, gRainRegion.left, gRainRegion.top, gRainRegion.right, gRainRegion.bottom, Get16BPPColor( FROMRGB( 0, 0, 0 ) ) ); +} + +UINT16 GetDropColor() +{ + UINT32 uiRGBPart = 32 + ( 15 - GetTimeOfDayAmbientLightLevel() ) * 8; + + uiRGBPart = max( 0, uiRGBPart ); + uiRGBPart = min( 255, uiRGBPart ); + + return Get16BPPColor( FROMRGB( uiRGBPart, uiRGBPart, uiRGBPart ) ); +} + +void RenderRainOnSurface() +{ + UINT8 *pDestBuf; + UINT32 uiDestPitchBYTES; + UINT32 uiIndex; + UINT16 sDropsColor = GetDropColor(); + + pDestBuf = LockVideoSurface( guiRainRenderSurface, &uiDestPitchBYTES ); + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, gsVIEWPORT_WINDOW_START_Y, SCREEN_WIDTH, gsVIEWPORT_WINDOW_END_Y - gsVIEWPORT_WINDOW_START_Y ); + + for( uiIndex = 0; uiIndex < guiCurrMaxAmountOfRainDrops; ++uiIndex ) + { + TRainDrop *pCurr = &pRainDrops[ uiIndex ]; + + if( !pCurr->fAlive )continue; + + LineDraw( TRUE, pCurr->fpX, pCurr->fpY, pCurr->fpX + pCurr->fpEndRelX, pCurr->fpY + pCurr->fpEndRelY, sDropsColor, pDestBuf ); + } + + UnLockVideoSurface( guiRainRenderSurface ); +} + +void GenerateRainMaximums() +{ + if( gbCurrentRainIntensity == 1 ) + { + fpMinDropAngleOfFalling = 45; + fpMaxDropAngleOfFalling = 135; + }else + if( Random( 2 ) ) + { + fpMinDropAngleOfFalling = 20; + fpMaxDropAngleOfFalling = 70; + }else{ + fpMinDropAngleOfFalling = 110; + fpMaxDropAngleOfFalling = 160; + } + + fpCurrDropAngleOfFalling = fpMinDropAngleOfFalling + Random( fpMaxDropAngleOfFalling - fpMinDropAngleOfFalling ); + + fpMinDropLength = MIN_DROP_LENGTH + ADD_DROP_LENGTH_IF_STORM * ( gbCurrentRainIntensity - 1 ); + fpMaxDropLength = fpMinDropLength + DROP_LENGTH_RANGE; + + fpCurrDropLength = fpMinDropLength + Random( fpMaxDropLength - fpMinDropLength ); + + fpMinDropSpeed = BASE_DROP_SPEED * gbCurrentRainIntensity; + fpMaxDropSpeed = fpMinDropSpeed + DROP_SPEED_RANGE; + + fpCurrDropSpeed = fpMinDropSpeed + Random( fpMaxDropSpeed - fpMinDropSpeed ); + +} + +void UpdateRainDropsProperities() +{ + fpCurrDropAngleOfFalling += Random( 1000 * DROP_ANGLE_CHANGE_RATE * gbCurrentRainIntensity * 2 ) / 1000.0f - DROP_ANGLE_CHANGE_RATE * gbCurrentRainIntensity; + + fpCurrDropAngleOfFalling = max( fpMinDropAngleOfFalling, fpCurrDropAngleOfFalling ); + fpCurrDropAngleOfFalling = min( fpMaxDropAngleOfFalling, fpCurrDropAngleOfFalling ); + + + fpCurrDropLength += Random( 1000 * DROP_LENGTH_CHANGE_RATE * 2 ) / 1000.0f - DROP_LENGTH_CHANGE_RATE; + + fpCurrDropLength = max( fpMinDropLength, fpCurrDropLength ); + fpCurrDropLength = min( fpMaxDropLength, fpCurrDropLength ); + + + fpCurrDropSpeed += Random( 1000 * DROP_SPEED_CHANGE_RATE * 2 ) / 1000.0f - DROP_SPEED_CHANGE_RATE; + + fpCurrDropSpeed = max( fpMinDropSpeed, fpCurrDropSpeed ); + fpCurrDropSpeed = min( fpMaxDropSpeed, fpCurrDropSpeed ); + + +} + +void RandomizeRainDropsPosition() +{ + UINT32 uiIndex; + UINT32 ubMoveTo; + + for( uiIndex = 0; uiIndex < guiCurrMaxAmountOfRainDrops; ++uiIndex ) + { + TRainDrop *pCurr = &pRainDrops[ uiIndex ]; + + if( !pCurr->fAlive )continue; + + if( pCurr->uiAmountOfTicksToLive ) + { + ubMoveTo = Random( pCurr->uiAmountOfTicksToLive ) + 1; + + while( ubMoveTo < pCurr->uiAmountOfTicksToLive ) + { + pCurr->fpX += pCurr->fpIncrX; + pCurr->fpY += pCurr->fpIncrY; + pCurr->uiAmountOfTicksToLive--; + } + } + } + +} + +void RainClipVideoOverlay() +{ + UINT32 uiIndex; + BACKGROUND_SAVE *pCurr; + + for( uiIndex = 0; uiIndex < guiNumVideoOverlays ; ++uiIndex ) + { + pCurr = gVideoOverlays[ uiIndex ].pBackground; + + if( pCurr->sLeft < gRainRegion.right || + pCurr->sTop < gRainRegion.bottom || + pCurr->sRight >= gRainRegion.left || + pCurr->sBottom >= gRainRegion.top ) + ColorFillVideoSurfaceArea( guiRainRenderSurface, pCurr->sLeft, pCurr->sTop, pCurr->sRight, pCurr->sBottom, Get16BPPColor( FROMRGB( 0, 0, 0 ) ) ); + } +} + +void RenderRain() +{ + if( !GetRainIntensityFromEnvWeather() && gbCurrentRainIntensity ) + { + gbCurrentRainIntensity = GetRainIntensityFromEnvWeather(); + ResetRain(); + } + + if( !IsItAllowedToRenderRain() )return; + + if( guiCurrentScreen == SHOPKEEPER_SCREEN ) + { + ColorFillVideoSurfaceArea( guiRainRenderSurface, SKI_X_OFFSET, SKI_Y_OFFSET, 535, 340, Get16BPPColor( FROMRGB( 0, 0, 0 ) ) ); + return; + } + + if( InOverheadMap() ) + { + // WANNE 2 + ColorFillVideoSurfaceArea( guiRainRenderSurface, OM_X_OFFSET, OM_Y_OFFSET, SCREEN_WIDTH, SCREEN_HEIGHT - 120, Get16BPPColor( FROMRGB( 0, 0, 0 ) ) ); + return; + } + + if( fFirstTime ) + { + InitializeRainData(); + fFirstTime = FALSE; + } + + if( GetJA2Clock() < guiLastRainUpdate ) + guiLastRainUpdate = GetJA2Clock(); + + if( GetJA2Clock() < guiLastRainUpdate + 1000 / RAIN_UPDATE_RATE ) + return; + else + guiLastRainUpdate = GetJA2Clock(); + + if( gbCurrentRainIntensity != GetRainIntensityFromEnvWeather() ) + { + gbCurrentRainIntensity = GetRainIntensityFromEnvWeather(); + ResetRain(); + GenerateRainDropsList(); + GenerateRainMaximums(); + + + guiCurrAmountOfDeadRainDrops = guiCurrMaxAmountOfRainDrops; + + CreateRainDrops(); + RandomizeRainDropsPosition(); + } + + guiCurrAmountOfDeadRainDrops = 0; + + UpdateRainDropsProperities(); + UpdateRainDrops(); + KillOutOfRegionRainDrops(); + CreateRainDrops(); + + BlankRainRenderSurface(); + RenderRainOnSurface(); + + RainClipVideoOverlay(); + + if( gfInTalkPanel ) + { + ColorFillVideoSurfaceArea( guiRainRenderSurface, gTalkPanel.sX, gTalkPanel.sY, gTalkPanel.sX + gTalkPanel.usWidth, gTalkPanel.sY + gTalkPanel.usHeight, Get16BPPColor( FROMRGB( 0, 0, 0 ) ) ); + if ( gTalkPanel.fRenderSubTitlesNow ) + { + if( gPopUpTextBox ) + ColorFillVideoSurfaceArea( guiRainRenderSurface, gTalkPanel.sPopupX, gTalkPanel.sPopupY, (INT16)( gTalkPanel.sPopupX + gPopUpTextBox->sWidth ), (INT16)( gTalkPanel.sPopupY + gPopUpTextBox->sHeight ), Get16BPPColor( FROMRGB( 0, 0, 0 ) ) ); + } + } + +} diff --git a/Tactical/Rain.h b/Tactical/Rain.h new file mode 100644 index 000000000..b22ba4f0b --- /dev/null +++ b/Tactical/Rain.h @@ -0,0 +1,7 @@ +#ifndef ___RAIN_H___ +#define ___RAIN_H___ + +BOOLEAN IsItAllowedToRenderRain(); +void RenderRain(); + +#endif \ No newline at end of file diff --git a/Tactical/Tactical.vcproj b/Tactical/Tactical.vcproj index 53fd59e8e..8afab9f18 100644 --- a/Tactical/Tactical.vcproj +++ b/Tactical/Tactical.vcproj @@ -3732,6 +3732,9 @@ BrowseInformation="1"/> + + + + diff --git a/Tactical/TeamTurns.cpp b/Tactical/TeamTurns.cpp index 3cd7fe20c..4c21ff0b5 100644 --- a/Tactical/TeamTurns.cpp +++ b/Tactical/TeamTurns.cpp @@ -361,6 +361,10 @@ void EndTurnEvents( void ) DecayRottingCorpseAIWarnings(); } +//rain +BOOLEAN LightningEndOfTurn( UINT8 ubTeam ); +//end rain + void BeginTeamTurn( UINT8 ubTeam ) { DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"BeginTeamTurn"); @@ -368,6 +372,11 @@ void BeginTeamTurn( UINT8 ubTeam ) UINT8 ubID; SOLDIERTYPE *pSoldier; + //rain + if( !LightningEndOfTurn( ubTeam ) )return; + //end rain + + while( 1 ) { if ( ubTeam > LAST_TEAM ) diff --git a/Tactical/Turn Based Input.cpp b/Tactical/Turn Based Input.cpp index 39406299c..380bee5fc 100644 --- a/Tactical/Turn Based Input.cpp +++ b/Tactical/Turn Based Input.cpp @@ -1513,6 +1513,32 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) } } + + /// Allow to save everywhere + if ((InputEvent.usEvent == KEY_DOWN )&& ( InputEvent.usParam == 'l') ) + { + if( InputEvent.usKeyState & ALT_DOWN ) + { + if ( !( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) ) + { + LeaveTacticalScreen( GAME_SCREEN ); + DoQuickLoad(); + } + } + else if( InputEvent.usKeyState & CTRL_DOWN ) + { + if ( !( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) ) + { + gfSaveGame = FALSE; + gfCameDirectlyFromGame = TRUE; + + guiPreviousOptionScreen = GAME_SCREEN; + LeaveTacticalScreen( SAVE_LOAD_SCREEN ); + } + } + } + + // Break of out IN CONV... if ( CHEATER_CHEAT_LEVEL( ) ) { @@ -2734,7 +2760,7 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) #endif case 'l': - +/* if( fAlt ) { if ( !( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) ) @@ -2756,16 +2782,16 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) guiPreviousOptionScreen = GAME_SCREEN; LeaveTacticalScreen( SAVE_LOAD_SCREEN ); } -/* +*//* if ( INFORMATION_CHEAT_LEVEL( ) ) { *puiNewEvent = I_LEVELNODEDEBUG; CountLevelNodes(); } -*/ +*//* } else - { +*/ { // nothing in hand and either not in SM panel, or the matching button is enabled if we are in SM panel if ( ( gpItemPointer == NULL ) && ( ( gsCurInterfacePanel != SM_PANEL ) || ( ButtonList[ iSMPanelButtons[ LOOK_BUTTON ] ]->uiFlags & BUTTON_ENABLED ) ) ) diff --git a/Tactical/Weapons.cpp b/Tactical/Weapons.cpp index e8aaeb45a..9ccd08944 100644 --- a/Tactical/Weapons.cpp +++ b/Tactical/Weapons.cpp @@ -44,6 +44,12 @@ #include "XML.h" #endif +//rain +#define WEAPON_RELIABILITY_REDUCTION_PER_RAIN_INTENSITY 9 +extern INT8 gbCurrentRainIntensity; +//end rain + + #define MINCHANCETOHIT 1 #define MAXCHANCETOHIT 99 @@ -1055,6 +1061,10 @@ void AdjustImpactByHitLocation( INT32 iImpact, UINT8 ubHitLocation, INT32 * piNe // #define TESTGUNJAM +//rain +extern INT8 gbCurrentRainIntensity; +//end rain + BOOLEAN CheckForGunJam( SOLDIERTYPE * pSoldier ) { OBJECTTYPE * pObj; @@ -1069,7 +1079,12 @@ BOOLEAN CheckForGunJam( SOLDIERTYPE * pSoldier ) if (pObj->bGunAmmoStatus > 0) { // gun might jam, figure out the chance - iChance = (80 - pObj->bGunStatus); + //iChance = (80 - pObj->bGunStatus); + + //rain + iChance = (80 - 90 - pObj->bGunStatus) + WEAPON_RELIABILITY_REDUCTION_PER_RAIN_INTENSITY * gbCurrentRainIntensity; + //end rain + // CJC: removed reliability from formula... @@ -1080,6 +1095,10 @@ BOOLEAN CheckForGunJam( SOLDIERTYPE * pSoldier ) // increased by 20% per negative point... //iChance = iChance * (10 - Item[pObj->usItem].bReliability * 2) / 10; + //rain + iChance = iChance * (10 - Item[pObj->usItem].bReliability * 2) / 10; + //end rain + if (pSoldier->bDoBurst > 1) { // if at bullet in a burst after the first, higher chance @@ -3211,7 +3230,11 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, UINT16 sGridNo, UINT8 ubAimTime { //SOLDIERTYPE *vicpSoldier; SOLDIERTYPE * pTarget; - INT32 iChance, iRange, iSightRange, iMaxRange, iBonus; //, minRange; + //rain + //INT32 iChance, iRange, iSightRange, iMaxRange, iBonus; //, minRange; + INT32 iChance, iRange, iSightRange, iMaxRange, iScopeBonus, iBonus; //, minRange; + //end rain + INT32 iGunCondition, iMarksmanship; INT32 iPenalty; UINT16 usInHand; @@ -3472,6 +3495,11 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, UINT16 sGridNo, UINT8 ubAimTime // // adjust for scope condition, only has full affect at 100% // iScopeBonus = (iScopeBonus * WEAPON_STATUS_MOD(pInHand->bAttachStatus[bAttachPos])) / 100; + //rain + // reduce scope effectiveness when it's raining + iScopeBonus /= 1 + gbCurrentRainIntensity; + //end rain + // // reduce effective range by the bonus obtained from the scope // iSightRange -= iScopeBonus; // if (iSightRange < 1) diff --git a/Tactical/opplist.cpp b/Tactical/opplist.cpp index 38d94e244..692d5caf2 100644 --- a/Tactical/opplist.cpp +++ b/Tactical/opplist.cpp @@ -44,6 +44,10 @@ #include "SkillCheck.h" #endif +//rain +#define VIS_DIST_DECREASE_PER_RAIN_INTENSITY 20 +//end rain + #define WE_SEE_WHAT_MILITIA_SEES_AND_VICE_VERSA extern void SetSoldierAniSpeed( SOLDIERTYPE *pSoldier ); @@ -255,6 +259,14 @@ UINT8 gubSightFlags = 0; } +//rain +extern INT8 gbCurrentRainIntensity; +extern BOOLEAN gfLightningInProgress; +extern BOOLEAN gfHaveSeenSomeone; +extern UINT8 ubRealAmbientLightLevel; +//end rain + + INT16 AdjustMaxSightRangeForEnvEffects( SOLDIERTYPE *pSoldier, INT8 bLightLevel, INT16 sDistVisible ) { INT16 sNewDist = 0; @@ -264,8 +276,16 @@ INT16 AdjustMaxSightRangeForEnvEffects( SOLDIERTYPE *pSoldier, INT8 bLightLevel, // Adjust it based on weather... if ( guiEnvWeather & ( WEATHER_FORECAST_SHOWERS | WEATHER_FORECAST_THUNDERSHOWERS ) ) { - sNewDist = sNewDist * 70 / 100; + //sNewDist = sNewDist * 70 / 100; + //rain + sNewDist = sNewDist * ( 100 - VIS_DIST_DECREASE_PER_RAIN_INTENSITY * gbCurrentRainIntensity ) / 100; + //end rain } + + //rain + if( gfLightningInProgress ) + sNewDist += sNewDist * ( ubRealAmbientLightLevel ) / 10; // 10% per dark level + //end rain return( sNewDist ); } @@ -785,6 +805,7 @@ void HandleSight(SOLDIERTYPE *pSoldier, UINT8 ubSightFlags) pSoldier->bNewOppCnt = 0; pSoldier->bNeedToLook = FALSE; + // Temporary for opplist synching - disable random order radioing #ifndef RECORDOPPLIST // if this soldier's NOT on our team (MAY be under our control, though!) @@ -839,7 +860,6 @@ void HandleSight(SOLDIERTYPE *pSoldier, UINT8 ubSightFlags) // CJC August 13 2002: at the end of handling sight, reset sight flags to allow interrupts in case an audio cue should // cause someone to see an enemy gubSightFlags |= SIGHT_INTERRUPT; - } @@ -1028,7 +1048,6 @@ INT16 DistanceVisible( SOLDIERTYPE *pSoldier, INT8 bFacingDir, INT8 bSubjectDir, //bSubjectDir = atan8(pSoldier->sX,pSoldier->sY,pOpponent->sX,pOpponent->sY); } - if ( !TANK( pSoldier ) && ( bFacingDir == DIRECTION_IRRELEVANT || (pSoldier->uiStatusFlags & SOLDIER_ROBOT) || (pSubject && pSubject->fMuzzleFlash) ) ) { sDistVisible = MaxDistanceVisible(); @@ -1420,6 +1439,7 @@ void ManLooksForOtherTeams(SOLDIERTYPE *pSoldier) UINT32 uiLoop; SOLDIERTYPE *pOpponent; + #ifdef TESTOPPLIST DebugMsg( TOPIC_JA2OPPLIST, DBG_LEVEL_3, String("MANLOOKSFOROTHERTEAMS ID %d(%S) team %d side %d",pSoldier->ubID,pSoldier->name,pSoldier->bTeam,pSoldier->bSide)); @@ -1457,7 +1477,6 @@ void ManLooksForOtherTeams(SOLDIERTYPE *pSoldier) } } } - } void HandleManNoLongerSeen( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pOpponent, INT8 * pPersOL, INT8 * pbPublOL ) @@ -1550,6 +1569,7 @@ INT16 ManLooksForMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, UINT8 ubCall INT16 sDistVisible,sDistAway; INT8 *pPersOL,*pbPublOL; + /* if (ptr->guynum >= NOBODY) { @@ -1593,6 +1613,8 @@ INT16 ManLooksForMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, UINT8 ubCall return(FALSE); } + + // if we're somehow looking for a guy who is inactive, at base, or already dead if (!pOpponent->bActive || !pOpponent->bInSector || pOpponent->bLife <= 0 || pOpponent->sGridNo == NOWHERE ) { @@ -1696,6 +1718,7 @@ INT16 ManLooksForMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, UINT8 ubCall pPersOL = &(pSoldier->bOppList[pOpponent->ubID]); pbPublOL = &(gbPublicOpplist[pSoldier->bTeam][pOpponent->ubID]); + // if soldier is known about (SEEN or HEARD within last few turns) if (*pPersOL || *pbPublOL) { @@ -1791,6 +1814,8 @@ INT16 ManLooksForMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, UINT8 ubCall } + + return(bSuccess); } @@ -2256,6 +2281,9 @@ else // then locate to him and set his locator flag bDoLocate = TRUE; + //rain + if( gfLightningInProgress ) gfHaveSeenSomeone = TRUE; + //end rain } // make opponent visible (to us) @@ -2321,7 +2349,10 @@ else { if (!pOpponent->bNeutral && (pSoldier->bSide != pOpponent->bSide)) { - SlideTo(0,pOpponent->ubID, pSoldier->ubID, SETLOCATOR); + //SlideTo(0,pOpponent->ubID, pSoldier->ubID, SETLOCATOR); + //rain + SlideTo(0,pOpponent->ubID, pSoldier->ubID, SETLOCATORFAST); + //end rain } } } diff --git a/TileEngine/environment.cpp b/TileEngine/environment.cpp index d46d7c178..81007a62b 100644 --- a/TileEngine/environment.cpp +++ b/TileEngine/environment.cpp @@ -158,6 +158,10 @@ BOOLEAN gfDoLighting = FALSE; UINT8 gubDesertTemperature = 0; UINT8 gubGlobalTemperature = 0; +//rain +extern BOOLEAN gfAllowRain; +//end rain + // local prototypes void EnvDoLightning(void); @@ -201,12 +205,12 @@ void EnvironmentController( BOOLEAN fCheckForLights ) // ONly do indooors if( !gfBasement && !gfCaves ) { -#if 0 +//#if 0 //rain if ( guiEnvWeather & ( WEATHER_FORECAST_THUNDERSHOWERS | WEATHER_FORECAST_SHOWERS ) ) { if ( guiRainLoop == NO_SAMPLE ) { - guiRainLoop = PlayJA2Ambient( RAIN_1, MIDVOLUME, 0 ); + guiRainLoop = PlayJA2Ambient( RAIN_1, BTNVOLUME, 0 ); } // Do lightning if we want... @@ -224,7 +228,7 @@ void EnvironmentController( BOOLEAN fCheckForLights ) guiRainLoop = NO_SAMPLE; } } -#endif +//#endif //rain } if ( gfDoLighting && fCheckForLights ) @@ -236,7 +240,7 @@ void EnvironmentController( BOOLEAN fCheckForLights ) if( !gfBasement && !gfCaves ) { // Rain storms.... -#if 0 +//#if 0 //rain if ( guiEnvWeather & ( WEATHER_FORECAST_THUNDERSHOWERS | WEATHER_FORECAST_SHOWERS ) ) { // Thunder showers.. make darker @@ -249,7 +253,7 @@ void EnvironmentController( BOOLEAN fCheckForLights ) ubLightAdjustFromWeather = (UINT8)(__min( gubEnvLightValue+1, NORMAL_LIGHTLEVEL_NIGHT )); } } -#endif +//#endif //rain } @@ -355,10 +359,20 @@ void BuildDayAmbientSounds( ) } - guiRainLoop = NO_SAMPLE; + //guiRainLoop = NO_SAMPLE; + //rain + if ( guiRainLoop != NO_SAMPLE ) + { + SoundStop( guiRainLoop ); + guiRainLoop = NO_SAMPLE; + } + //end rain } +extern UINT16 gusRainChancePerDay, gusRainMinLength, gusRainMaxLength; //rain + + void ForecastDayEvents( ) { UINT32 uiOldDay; @@ -383,6 +397,32 @@ void ForecastDayEvents( ) // ATE: Don't forecast if start of game... if ( guiEnvDay > 1 ) { + //rain + if ( Random( 100 ) < gusRainChancePerDay ) + { + // Add rain! + // Between 6:00 and 10:00 + uiStartTime = (UINT32)( Random( 1440 - 1 -gusRainMaxLength ) ); + // Between 5 - 15 miniutes + uiEndTime = uiStartTime + ( gusRainMinLength + Random( gusRainMaxLength - gusRainMinLength ) ); + + ubStormIntensity = 0; + + // Randomze for a storm! + if ( Random( 10 ) < 5 ) + { + ubStormIntensity = 1; + } + + if( gfAllowRain ) AddSameDayRangedStrategicEvent( EVENT_RAINSTORM, uiStartTime, uiEndTime - uiStartTime, ubStormIntensity ); + + //AddSameDayStrategicEvent( EVENT_BEGINRAINSTORM, uiStartTime, ubStormIntensity ); + //AddSameDayStrategicEvent( EVENT_ENDRAINSTORM, uiEndTime, 0 ); + } + //end rain + + + /* // Should it rain...? if ( Random( 100 ) < 20 ) { @@ -406,6 +446,7 @@ void ForecastDayEvents( ) //AddSameDayStrategicEvent( EVENT_BEGINRAINSTORM, uiStartTime, ubStormIntensity ); //AddSameDayStrategicEvent( EVENT_ENDRAINSTORM, uiEndTime, 0 ); } + */ } } @@ -422,6 +463,272 @@ void EnvDisableTOD(void) } + +//rain +UINT32 guiMinLightningInterval = 5; +UINT32 guiMaxLightningInterval = 15; + +UINT32 guiMinDLInterval = 1; +UINT32 guiMaxDLInterval = 5; + +UINT32 guiProlongLightningIfSeenSomeone = 5; +UINT32 guiChanceToDoLightningBetweenTurns = 20; + + + // 60 = 1 second +#define MIN_LIGHTNING_INTERVAL ( 60 * guiMinLightningInterval ) +#define MAX_LIGHTNING_INTERVAL ( 60 * guiMaxLightningInterval ) + +#define MAX_DELAYED_SOUNDS 10 +#define NO_DL_SOUND 0xFFFFFFFF + +// 1000 = 1 second +#define MIN_DL_INTERVAL ( 1000 * guiMinDLInterval ) +#define MAX_DL_INTERVAL ( 1000 * guiMaxDLInterval ) + +#define EXTRA_ADD_VIS_DIST_IF_SEEN_SOMEONE ( 1000 * guiProlongLightningIfSeenSomeone ) +#define CHANCE_TO_DO_LIGHTNING_BETWEEN_TURNS guiChanceToDoLightningBetweenTurns + +BOOLEAN gfLightningInProgress = FALSE; +BOOLEAN gfHaveSeenSomeone = FALSE; + +UINT8 ubRealAmbientLightLevel = 0; +BOOLEAN gfTurnBasedDoLightning = FALSE; +BOOLEAN gfTurnBasedLightningEnd = FALSE; + +BOOLEAN gfWasTurnBasedWhenLightningBegin = FALSE; + +UINT8 gubLastTeamLightning; + +#define IS_TURNBASED ( gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT ) + +void BeginTeamTurn( UINT8 ubTeam ); + + + + +void EnvDoLightning(void) +{ + static UINT32 uiCount=10, uiIndex=0, uiStrike=0, uiFrameNext=0; + static UINT8 ubLevel=0, ubLastLevel=0; + static UINT32 uiLastUpdate = 0xFFFFFFFF; + static UINT32 uiTurnOffExtraVisDist = 0xFFFFFFFF; + static UINT32 pDelayedSounds[ MAX_DELAYED_SOUNDS ]; + UINT32 uiDSIndex; + + if( GetJA2Clock() < uiLastUpdate ) + { + uiLastUpdate = 0; + memset( pDelayedSounds, NO_DL_SOUND, sizeof( UINT32 ) * MAX_DELAYED_SOUNDS ); + } + + if( GetJA2Clock() < uiLastUpdate + 1000 / 60 )return; + else + uiLastUpdate = GetJA2Clock(); + + if( GetJA2Clock() > uiTurnOffExtraVisDist ) + { + AllTeamsLookForAll( FALSE ); + uiTurnOffExtraVisDist = 0xFFFFFFFF; + + if( gfTurnBasedLightningEnd ) + { + BeginTeamTurn( gubLastTeamLightning ); + gfTurnBasedLightningEnd = FALSE; + } + + } + + for( uiDSIndex = 0; uiDSIndex < MAX_DELAYED_SOUNDS; ++uiDSIndex ) + if( GetJA2Clock() > pDelayedSounds[ uiDSIndex ] ) + { + PlayJA2Ambient(LIGHTNING_1+Random(2), HIGHVOLUME, 1); + pDelayedSounds[ uiDSIndex ] = NO_DL_SOUND; + } + + if ( gfPauseDueToPlayerGamePause ) + { + return; + } + + if( IS_TURNBASED && !gfLightningInProgress ) + { + if( !gfTurnBasedDoLightning ) + { + return; + } + else + { + gfTurnBasedDoLightning = FALSE; + uiFrameNext = 1; + uiCount = 0; + gfTurnBasedLightningEnd = TRUE; + } + } + + uiCount++; + if(uiCount >= (uiFrameNext+10)) + { + if( gfHaveSeenSomeone && gfWasTurnBasedWhenLightningBegin ) + uiTurnOffExtraVisDist = GetJA2Clock() + EXTRA_ADD_VIS_DIST_IF_SEEN_SOMEONE; + else + uiTurnOffExtraVisDist = GetJA2Clock(); + + gfLightningInProgress = FALSE; + gfHaveSeenSomeone = FALSE; + + uiCount=0; + uiIndex=0; + ubLevel=0; + ubLastLevel=0; + + uiStrike=Random(3); + uiFrameNext=MIN_LIGHTNING_INTERVAL+Random(MAX_LIGHTNING_INTERVAL - MIN_LIGHTNING_INTERVAL); + } + else if(uiCount >= uiFrameNext) + { + if(uiCount == uiFrameNext) + { + //EnvStopCrickets(); +// PlayJA2Ambient(LIGHTNING_1+Random(2), HIGHVOLUME, 1); + for( uiDSIndex = 0; uiDSIndex < MAX_DELAYED_SOUNDS; ++uiDSIndex ) + if( pDelayedSounds[ uiDSIndex ] == NO_DL_SOUND ) + { + pDelayedSounds[ uiDSIndex ] = GetJA2Clock() + MIN_DL_INTERVAL+Random(MAX_DL_INTERVAL - MIN_DL_INTERVAL); + break; + } + + ubRealAmbientLightLevel = ubAmbientLightLevel; + + gfWasTurnBasedWhenLightningBegin = IS_TURNBASED; + + gfLightningInProgress = TRUE; + AllTeamsLookForAll( FALSE ); + } + + while(uiCount > ((UINT32)ubLightningTable[uiStrike][uiIndex][0] + uiFrameNext)) + uiIndex++; + + ubLastLevel=ubLevel; + ubLevel=min( ubRealAmbientLightLevel - 1, ubLightningTable[uiStrike][uiIndex][1] ); + +/* // ATE: Don't modify if scrolling! + if ( gfScrollPending || gfScrollInertia ) + { + } + else*/ + { + if(ubLastLevel!=ubLevel) + { + if(ubLevel > ubLastLevel) + { + LightAddBaseLevel(0, (UINT8)(ubLevel-ubLastLevel)); + if(ubLevel > 0) + RenderSetShadows(TRUE); + } + else + { +// LightSubtractBaseLevel(0, (UINT8)(ubLastLevel-ubLevel)); + LightSetBaseLevel( ubRealAmbientLightLevel - ubLevel ); + if(ubLevel > 0) + RenderSetShadows(TRUE); + } + SetRenderFlags(RENDER_FLAG_FULL); + } + } + + } +} + +BOOLEAN LightningEndOfTurn( UINT8 ubTeam ) +{ + if( !(guiEnvWeather & WEATHER_FORECAST_THUNDERSHOWERS) )return TRUE; + if( Random(100) >= CHANCE_TO_DO_LIGHTNING_BETWEEN_TURNS ) return TRUE; + + if( !gfTurnBasedLightningEnd ) + { + gfTurnBasedDoLightning = TRUE; + gubLastTeamLightning = ubTeam; + EnvDoLightning(); + return FALSE; + } + else + { + return TRUE; + } +} + +UINT8 GetTimeOfDayAmbientLightLevel() +{ + if ( SectorTemperature( GetWorldMinutesInDay(), gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) == HOT ) + { + return( HOT_DAY_LIGHTLEVEL ); + } + else + { + return( gubEnvLightValue ); + } +} + + +void EnvBeginRainStorm( UINT8 ubIntensity ) +{ + if( !gfBasement && !gfCaves ) + { + gfDoLighting = TRUE; + + #ifdef JA2TESTVERSION + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Starting Rain...." ); + #endif + + if ( ubIntensity == 1 ) + { + // Turn on rain storms + guiEnvWeather |= WEATHER_FORECAST_THUNDERSHOWERS; + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Storm started." ); + } + else + { + guiEnvWeather |= WEATHER_FORECAST_SHOWERS; + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Rain started." ); + } + } + +} + +void EnvEndRainStorm( ) +{ + gfDoLighting = TRUE; + +#ifdef JA2TESTVERSION + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Ending Rain...." ); +#endif + + if ( guiEnvWeather & WEATHER_FORECAST_THUNDERSHOWERS ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Storm ended." ); + } + else + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Rain ended." ); + } + + + guiEnvWeather &= (~WEATHER_FORECAST_THUNDERSHOWERS ); + guiEnvWeather &= (~WEATHER_FORECAST_SHOWERS ); +} + +//end rain + + + + + + + + + +/* void EnvDoLightning(void) { static UINT32 uiCount=0, uiIndex=0, uiStrike=0, uiFrameNext=1000; @@ -531,6 +838,8 @@ void EnvEndRainStorm( ) guiEnvWeather &= (~WEATHER_FORECAST_THUNDERSHOWERS ); guiEnvWeather &= (~WEATHER_FORECAST_SHOWERS ); } +*/ + void TurnOnNightLights() { diff --git a/TileEngine/physics.cpp b/TileEngine/physics.cpp index bc11b48b3..2cd67691d 100644 --- a/TileEngine/physics.cpp +++ b/TileEngine/physics.cpp @@ -670,16 +670,15 @@ BOOLEAN PhysicsHandleCollisions( REAL_OBJECT *pObject, INT32 *piCollisionID, rea } } - // Check for -ve velocity still... - //if ( pObject->Velocity.z <= EPSILONV && pObject->Velocity.z >= -EPSILONV && - // pObject->Velocity.y <= EPSILONV && pObject->Velocity.y >= -EPSILONV && - // pObject->Velocity.x <= EPSILONV && pObject->Velocity.x >= -EPSILONV ) - //{ - //PhysicsDeleteObject( pObject ); - // pObject->fAlive = FALSE; - // return( FALSE ); - //} + /*if ( pObject->Velocity.z <= EPSILONV && pObject->Velocity.z >= -EPSILONV && + pObject->Velocity.y <= EPSILONV && pObject->Velocity.y >= -EPSILONV && + pObject->Velocity.x <= EPSILONV && pObject->Velocity.x >= -EPSILONV ) + { + PhysicsDeleteObject( pObject ); + pObject->fAlive = FALSE; + return( FALSE ); + }*/ } return( TRUE ); diff --git a/TileEngine/renderworld.cpp b/TileEngine/renderworld.cpp index b3857ec16..9eaddcdf0 100644 --- a/TileEngine/renderworld.cpp +++ b/TileEngine/renderworld.cpp @@ -2800,6 +2800,12 @@ UINT32 cnt = 0; if ( gfScrollInertia == FALSE || (gRenderFlags&RENDER_FLAG_NOZ ) || (gRenderFlags&RENDER_FLAG_FULL ) || (gRenderFlags&RENDER_FLAG_MARKED ) ) { RenderDynamicWorld( ); + +/////////////////////////////////////////////////////////// + +// ColorFillVideoSurfaceArea( guiSAVEBUFFER, 0, gsVIEWPORT_WINDOW_END_Y, BP_SCREEN_WIDTH_CENTERED, SCREEN_HEIGHT, Get16BPPColor( FROMRGB( 16, 8, 0 ) ) ); + +/////////////////////////////////////////////////////////// } if ( gfScrollInertia ) @@ -3504,6 +3510,7 @@ BOOLEAN HandleScrollDirections( UINT32 ScrollFlags, INT16 sScrollXStep, INT16 sS return( fAGoodMove ); } +extern BOOLEAN gfNextRefreshFullScreen; void ScrollWorld( ) { @@ -3752,6 +3759,8 @@ void ScrollWorld( ) // Now we actually begin our scrolling HandleScrollDirections( ScrollFlags, sScrollXStep, sScrollYStep, &sTempRenderCenterX, &sTempRenderCenterY, FALSE ); + + if( gfNextRefreshFullScreen ) SetRenderFlags( RENDER_FLAG_FULL ); } } else diff --git a/gameloop.cpp b/gameloop.cpp index 41e3ce9f3..7e588321d 100644 --- a/gameloop.cpp +++ b/gameloop.cpp @@ -29,6 +29,10 @@ #include "HelpScreen.h" #endif +// rain +#include "Rain.h" +// end rain + UINT32 guiCurrentScreen; UINT32 guiPendingScreen = NO_PENDING_SCREEN; @@ -162,6 +166,9 @@ void ShutdownGame(void) // the state of the game (i.e. Main Menu, PC Generation, Combat loop, etc....) // This function exits constantly and reenters constantly +// rain +static BOOLEAN gfSkipFrame = FALSE; + void GameLoop(void) { // DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"GameLoop"); @@ -309,6 +316,14 @@ void GameLoop(void) guiCurrentScreen = uiOldScreen; } + // rain + RenderRain(); + + if( gfSkipFrame ) + gfSkipFrame = FALSE; + else + // end rain + //DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"GameLoop: refresh screen"); RefreshScreen( NULL ); @@ -339,6 +354,10 @@ void SetPendingNewScreen( UINT32 uiNewScreen ) guiPendingScreen = uiNewScreen; } +// rain +extern UINT32 guiRainLoop; +// end rain + // Gets called when the screen changes, place any needed in code in here void HandleNewScreenChange( UINT32 uiNewScreen, UINT32 uiOldScreen ) { @@ -348,6 +367,17 @@ void HandleNewScreenChange( UINT32 uiNewScreen, UINT32 uiOldScreen ) //reset the help screen NewScreenSoResetHelpScreen( ); } + + //rain + if( uiNewScreen == MAP_SCREEN ) + { + if ( guiRainLoop != NO_SAMPLE ) + { + SoundStop( guiRainLoop ); + guiRainLoop = NO_SAMPLE; + } + } + // end rain } void HandleShortCutExitState( void ) diff --git a/local.h b/local.h index aa78a6d55..09bc6fcc6 100644 --- a/local.h +++ b/local.h @@ -4,6 +4,13 @@ #include "Screens.h" +//rain +#include "NewGameSettings.h" +//end rain + + + + // // Make sure the application has a name //