From 89b4d71bf33e46266dd5150b91eda489173519a9 Mon Sep 17 00:00:00 2001 From: lalien Date: Wed, 19 Apr 2006 17:10:53 +0000 Subject: [PATCH] Data and Source v1.13 Mod High Resolution version from 2006-03-01 git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@23 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- Credits.cpp | 22 +- GameSettings.cpp | 5 + GameSettings.h | 5 + HelpScreen.cpp | 15 +- Init.cpp | 7 + JA2.sln | 10 +- JA2.suo | Bin 66560 -> 66560 bytes Laptop/laptop.cpp | 232 +- Laptop/mercs Account.cpp | 4 +- Options Screen.cpp | 1 + SCREENS.cpp | 4 + SaveLoadGame.cpp | 94 +- SaveLoadGame.h | 3 +- Standard Gaming Platform/Button System.cpp | 3 + Standard Gaming Platform/video.cpp | 1 + Strategic/Assignments.cpp | 65 +- Strategic/Auto Resolve.cpp | 80 +- Strategic/Game Clock.h | 15 +- Strategic/Map Screen Interface Border.cpp | 78 +- Strategic/Map Screen Interface Border.h | 13 +- Strategic/Map Screen Interface Bottom.cpp | 119 +- .../Map Screen Interface Map Inventory.cpp | 114 +- .../Map Screen Interface Map Inventory.h | 5 +- Strategic/Map Screen Interface Map.cpp | 88 +- Strategic/Map Screen Interface Map.h | 25 +- Strategic/Map Screen Interface.cpp | 38 +- Strategic/Map Screen Interface.h | 2 +- Strategic/Map Screen Interface_NEW.cpp | 6482 +++++++++++++++++ Strategic/Map Screen Interface_NEW.h | 606 ++ Strategic/Quest Debug System.cpp | 4 +- Strategic/Strategic AI.cpp | 8 +- Strategic/mapscreen.cpp | 458 +- Strategic/strategicmap.cpp | 31 +- Tactical/Auto Bandage.cpp | 7 +- Tactical/Campaign.cpp | 9 +- Tactical/Civ Quotes.cpp | 9 +- Tactical/Dialogue Control.cpp | 9 + Tactical/DisplayCover.cpp | 4 +- Tactical/End Game.cpp | 4 +- Tactical/Handle Items.cpp | 9 +- Tactical/Handle UI.cpp | 6 +- Tactical/Interface Items.cpp | 83 +- Tactical/Interface Panels.cpp | 44 +- Tactical/Inventory Choosing.cpp | 8 +- Tactical/Keys.cpp | 6 +- Tactical/Overhead.cpp | 2 + Tactical/Rotting Corpses.cpp | 4 +- Tactical/ShopKeeper Interface.cpp | 216 +- Tactical/SkillCheck.cpp | 14 +- Tactical/Soldier Ani.cpp | 8 +- Tactical/Soldier Control.cpp | 141 +- Tactical/Soldier Profile.h | 4 +- Tactical/Turn Based Input.cpp | 7 +- Tactical/Weapons.cpp | 2 +- Tactical/opplist.cpp | 50 +- Tactical/opplist.h | 2 +- TacticalAI/AIMain.cpp | 2 +- TacticalAI/CreatureDecideAction.cpp | 2 +- TacticalAI/DecideAction.cpp | 2 +- TileEngine/Buildings.cpp | 26 +- TileEngine/Radar Screen.cpp | 15 +- TileEngine/Radar Screen.h | 6 +- TileEngine/Tactical Placement GUI.cpp | 5 +- TileEngine/overhead map.cpp | 7 +- TileEngine/physics.cpp | 8 +- TileEngine/physics_v113.cpp | 2673 +++++++ Utils/PopUpBox.cpp | 5 +- Utils/_EnglishText.cpp | 5 +- Utils/_GermanText.cpp | 5 +- Utils/message.cpp | 13 +- local.h | 4 + 71 files changed, 11332 insertions(+), 731 deletions(-) create mode 100644 Strategic/Map Screen Interface_NEW.cpp create mode 100644 Strategic/Map Screen Interface_NEW.h create mode 100644 TileEngine/physics_v113.cpp diff --git a/Credits.cpp b/Credits.cpp index 9712a4aa..9d31ec96 100644 --- a/Credits.cpp +++ b/Credits.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "JA2 All.h" #include "Credits.h" @@ -128,7 +129,7 @@ enum #define CRDT_SPACE_BN_SECTIONS 50 #define CRDT_SPACE_BN_NODES 12 -#define CRDT_START_POS_Y 479 +#define CRDT_START_POS_Y (SCREEN_HEIGHT - 1) //479 #define CRDT_EYE_WIDTH 30 #define CRDT_EYE_HEIGHT 12 @@ -456,7 +457,20 @@ BOOLEAN EnterCreditsScreen() */ ColorFillVideoSurfaceArea( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0 ); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; - FilenameForBPP("INTERFACE\\Credits.sti", VObjectDesc.ImageFile); + + if (iResolution == 0) + { + FilenameForBPP("INTERFACE\\Credits.sti", VObjectDesc.ImageFile); + } + else if (iResolution == 1) + { + FilenameForBPP("INTERFACE\\Credits_800x600.sti", VObjectDesc.ImageFile); + } + else if (iResolution == 2) + { + FilenameForBPP("INTERFACE\\Credits_1024x768.sti", VObjectDesc.ImageFile); + } + CHECKF(AddVideoObject(&VObjectDesc, &guiCreditBackGroundImage )); VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; @@ -1032,7 +1046,9 @@ BOOLEAN DisplayCreditNode( CRDT_NODE *pCurrent ) //if the surface is at the bottom of the screen if( pCurrent->sOldPosY + pCurrent->sHeightOfString > CRDT_START_POS_Y ) { - INT16 sHeight = 480 - pCurrent->sOldPosY; + // WANNE 2 + INT16 sHeight = SCREEN_HEIGHT - pCurrent->sOldPosY; + //INT16 sHeight = 480 - pCurrent->sOldPosY; RestoreExternBackgroundRect( pCurrent->sOldPosX, pCurrent->sOldPosY, CRDT_WIDTH_OF_TEXT_AREA, sHeight ); } else if( pCurrent->sOldPosY > CRDT_LINE_NODE_DISAPPEARS_AT ) diff --git a/GameSettings.cpp b/GameSettings.cpp index 79903bbb..9604bca1 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -327,6 +327,11 @@ void LoadGameExternalOptions() gGameExternalOptions.iCustomPersonality = iniReader.ReadInteger("Options","CUSTOM_PERSONALITY",6); gGameExternalOptions.iCustomAttitude = iniReader.ReadInteger("Options","CUSTOM_ATTITUDE",0); + gGameExternalOptions.iEasyAPBonus = iniReader.ReadInteger("Options","NOVICE_AP_BONUS",0); + gGameExternalOptions.iExperiencedAPBonus = iniReader.ReadInteger("Options","EXPERIENCED_AP_BONUS",0); + gGameExternalOptions.iExpertAPBonus = iniReader.ReadInteger("Options","EXPERT_AP_BONUS",0); + gGameExternalOptions.iInsaneAPBonus = iniReader.ReadInteger("Options","INSANE_AP_BONUS",0); + } diff --git a/GameSettings.h b/GameSettings.h index 96e2184a..4e379094 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -172,6 +172,11 @@ typedef struct INT8 iCustomPersonality; INT8 iCustomAttitude; + INT8 iEasyAPBonus; + INT8 iExperiencedAPBonus; + INT8 iExpertAPBonus; + INT8 iInsaneAPBonus; + } GAME_EXTERNAL_OPTIONS; diff --git a/HelpScreen.cpp b/HelpScreen.cpp index 0d095243..4bb67d0f 100644 --- a/HelpScreen.cpp +++ b/HelpScreen.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "JA2 All.h" #include "HelpScreen.h" @@ -727,17 +728,9 @@ void RenderHelpScreen() { gfHaveRenderedFirstFrameToSaveBuffer = TRUE; - // WANNE: an exception occurs, when i try to open the help screen in laptop mode, so i put a try-catch block - // around this. I will fix that later. - __try - { - //blit everything to the save buffer ( cause the save buffer can bleed through ) - BlitBufferToBuffer(guiRENDERBUFFER, guiSAVEBUFFER, gHelpScreen.usScreenLocX, gHelpScreen.usScreenLocY, (UINT16)(gHelpScreen.usScreenLocX+gHelpScreen.usScreenWidth), (UINT16)(gHelpScreen.usScreenLocY+gHelpScreen.usScreenHeight) ); - } - __except(filter(GetExceptionCode(), GetExceptionInformation())) - { - } - + //blit everything to the save buffer ( cause the save buffer can bleed through ) + BlitBufferToBuffer(guiRENDERBUFFER, guiSAVEBUFFER, gHelpScreen.usScreenLocX, gHelpScreen.usScreenLocY, (UINT16)(gHelpScreen.usScreenWidth), (UINT16)(gHelpScreen.usScreenHeight) ); + UnmarkButtonsDirty( ); } diff --git a/Init.cpp b/Init.cpp index 088aef79..c2368bea 100644 --- a/Init.cpp +++ b/Init.cpp @@ -53,6 +53,7 @@ #include "Init.h" #include "jascreens.h" #include "XML.h" + #include "SaveLoadGame.h" #endif extern BOOLEAN GetCDromDriveLetter( STR8 pString ); @@ -360,6 +361,12 @@ UINT32 InitializeJA2(void) DetermineRGBDistributionSettings(); + // Snap: Init save game directory + if ( !InitSaveDir() ) + { + return( ERROR_SCREEN ); + } + #ifdef JA2BETAVERSION #ifdef JA2EDITOR diff --git a/JA2.sln b/JA2.sln index a5fad666..b9e9920f 100644 --- a/JA2.sln +++ b/JA2.sln @@ -33,14 +33,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Utils", "Utils\Utils.vcproj EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ja2", "JA2.vcproj", "{0795F6E2-EE5C-48C5-AB6B-11E64B7533D4}" ProjectSection(ProjectDependencies) = postProject - {5C428253-7443-4C4B-A5F2-E079DA2E6933} = {5C428253-7443-4C4B-A5F2-E079DA2E6933} - {FEE1FCB1-6A45-4247-A440-3561F33B16A3} = {FEE1FCB1-6A45-4247-A440-3561F33B16A3} {CB33540F-3AFF-4985-86FE-5E899B570133} = {CB33540F-3AFF-4985-86FE-5E899B570133} + {5C428253-7443-4C4B-A5F2-E079DA2E6933} = {5C428253-7443-4C4B-A5F2-E079DA2E6933} {94DA4574-7108-4CDA-B43F-DA83B1C3EDF6} = {94DA4574-7108-4CDA-B43F-DA83B1C3EDF6} - {6B1D57C9-A579-452E-8642-6ECF3E9FD399} = {6B1D57C9-A579-452E-8642-6ECF3E9FD399} - {F80B55A6-E228-4EB6-B915-4815E01CEA76} = {F80B55A6-E228-4EB6-B915-4815E01CEA76} - {4D15E8C7-9458-403C-A34B-15DF2CAF3277} = {4D15E8C7-9458-403C-A34B-15DF2CAF3277} {262D8F88-8266-4B16-999E-B5C0B12EFF01} = {262D8F88-8266-4B16-999E-B5C0B12EFF01} + {F80B55A6-E228-4EB6-B915-4815E01CEA76} = {F80B55A6-E228-4EB6-B915-4815E01CEA76} + {FEE1FCB1-6A45-4247-A440-3561F33B16A3} = {FEE1FCB1-6A45-4247-A440-3561F33B16A3} + {4D15E8C7-9458-403C-A34B-15DF2CAF3277} = {4D15E8C7-9458-403C-A34B-15DF2CAF3277} + {6B1D57C9-A579-452E-8642-6ECF3E9FD399} = {6B1D57C9-A579-452E-8642-6ECF3E9FD399} EndProjectSection EndProject Global diff --git a/JA2.suo b/JA2.suo index 268837e8b101da70e50f69a8e057e1368da06267..7c08a09a89810c54c61b538204c93be49c82cd11 100644 GIT binary patch literal 66560 zcmeI537i~76~=pWKp-SQIK(J8hASZ1?3LYY4#=J%AxmPyr9^SFJ4rU#?8My-0TUEN z1@BuBFBA_15kyh&K*S4F1o6HQyl+5JP=WaWx~6x!d#;|D+RfEHzi+y_ySnSut9q~A zdtKdq-@OMv_`y$2f5-_fCp+Vvr+4h;NP zfv2EzB5hU!CIGePB(N_y8tey-0SAC-U<#ND4g_=o=U{LMP#-vw^wBOaDp&%Rg44h<&;?EhD?l%JK3EA>fiuBm za27ZloC96}UI@+wtHF!Fi@|x|C7>H5K@SiQH?dv|)`9h)4`{!C32*z4m6~4Zr1%Zf z79Gw2>p|y2N{qf7?o1q!ceQPy<))dJJ-A}wH>$>y>5fZH&J~oHayG!{0qUKCiVF%| zBJ0@U&bTV|Ij`PX8S?B<-_>#kEimM4q;30H57UN2w8!Ac{vnes@BcAqLDfg{A{z2$ z^c|=oEg93YiaKwhydFwzBi)-`o3=0`=2jumzkCwgO3#q*?XY#(F!r2)rD;0$dDkdB;_Eefy-ZFM0b{e*ON(F8Yhq zQc24rZR#QAFMph2&fW2}*6L-_L%rznwaA9_Q4$GNt#zaqDIKQngXmJTC0UvP)Th>_ z&piXpDQRBLsIr0cdtA;)8!sW18J0U zm+mc%q||5hUrP>+can!b{?*&s>6L3ZYaKt0duOwEm}BeR-Wsk!_I3hFH6A=0pk^YC zf07kf+*yaqZ-oX){6-`+1(g~H3yr}u8UMs9m92$j(dD02j&rk=21~en*&iBTwu_ul#8jw%fv8os6KjiT+Q14!L2 zW_y#%jCE|SpsT85%0wJwzvEnUIDg^Z+~V5n3P(j6bxxfj(qJEV@g zjC^YB6#wj!4P(X~6_-RRBqkR{(*{J_kI4+b1t88TgNBn z{jlfC$1gbYQqFV+?_Sz+!j&6D>H@HmvP7Y*(Ige#NM{T{4)(kDt*rb$xSCC+(IID%s}&yfFuF<$B;m0<6xlwLoev$T zUOvgWhV>%$RHMfDQ=8WL~N$5Z6y(#RDs{fQ%wz?MSd&&7AZK^)1`Ws8l^GuEXXnKco21lfMlrO7Q zWovOSTI7$;>)Nc!7PdJ3bzVWuhoDD2FyBa2L-`&*qn7_@6*?}h{|lAx`NHjRM(R1& zQcd~t>D}^E->WJ3Wk*gRD*l0m3=K7D^9DliL^(8(xU00Dm1xy9X6EC|z2mF$r8H_($Dqa$S@HlQzMqsdaM zMO)5wwP%}qOd3_TTPORJcP{BxSD)6SQQO&Hsz$Y0YOr-mX%nN#Y|`TO412b!={L4% zG|}Pm`i;>Fwka|eey}a=YgwCA+tRXTT(?PCMl+Nm4Q9-=Nyq55rqS`ENvkKxrEt(_ z)H<|b9a?d&J90{o$_sAfCwo+SQ>kY6*Fj3wY@2J<){?J-vpQXCHL8tjc;PQ~_xE7p z8dSo8x$fv)eyr;Kx0>lw@~G#cy*klSv)JljOL|NitjX0` zUVJf%Z*6#Ov()m&J=0Td(=poijM4fwskR~YCSEdnRFy76HfhQ9uktKs<8RoeXf$Hu zHfgkFCmZ|JCS~Csztz1j7v=tZv6zn0sM3=i*n6GWce49tp*xMIEsa_Sn%Jj3(zw#M zbI76m(xb*wY#|lZ67(X3_Daq4_);X#i<;V_BiK@<(Bj2i?9r0pNhMmqX5SD+cC~;P zL$k-VU<;PVIWJObk1D&m$!42|`DITx8GFYjt(pEedQ=;Ys#vA&?8x$LbG4^p0CU)q zM%A3iHdmw8v!y%C%B%Qf9s6a=YHn2%ztS|S%~CVkqZBP>#y*>Lj9yC_jcb$E4A08b z8)iJRNl}n{rL?5cVK!;8rNfNQw@F!$OXanl(N;F88ar)ea~4b#kJ|Keo23R@u#|po zdei99Qb}*JN!3{NCZqkMQ!URS97(QJhZ-8njY#F9DA>1b-s>@PFnY9>A_qp_+oZ*o zzBkbbo0Mf_!4{3i>T7g;;dX4fChWLo*TPd;DOrE&>n1WOuUcMq2l-^}b&#hM3$UJb zb7ZT}=q{V3hWon5sZx59X)l{pc~scDTWxx~O&V?WB%{AA(pJcTop))8aBWbzE zoV`^Z_4uJDkKq}%cDS#n!h_>MtOw0A+}Tf!+u^uu(jdp$<2|41w`{`Y#p z5ch3H(ceT;uEh9lzjEJ662Cjf_z1FgqPN&0a_1U}a*YnN12%fO?Q|j~#y)D{H~K`2 z9oUeX*itLp62&bw8?6vWa7xix`64*^Ja`)|6npUb-#=E^gSWx`*n`jY-Zzb;*<-hz zQ9AZN!f)BrNE!A&Z1ipKm5X}MbnJgr=6|e6w~>k2Ydp|PH0yXresE8&*J@tExvvD5 zf>(i8gV%t|z~$hz;C0~j;0@r7;7#Do;4R>-;BDaT;2q$d;9cMfa3y#*xC*=nycfI= zydQi3Tn#=5J_N1-9|j)*9|a!+*8;`ruVZ~Z_yo8Cd=lIUZUUbIH-k@u&wyLNXTj&d zt>8BBdGH1BMerqXJNPoV1AGPC3BC%x2EGoy0lo?D0(XONfp3HFfP27q!M)%<@I7!p z_&)dn_#yZa_%Zki_$l}q_&HEre#!a)@GI~jcnJI&{096M{0{sc`~mzC{0aOS{000K z{0;maJPaNIkAi=Ie}c!rzrer2RUe5}6l-)`-W7tZu#h1(CJ3ZYlK@AgS zbh9HnGble3mCoF+*b_8cP$T8C5Q02}6@jI$jQj5|;|d?0Y%Zhn&0AhG@7fL&P-Np! z?tf1skM4bIDU#hi{Bi!TJ;3D5euH3&|5>&-)6^@#ml&7tNBV9H(<-7aefNo~Pg}+0v zC)*>HN=aiD=QH-2krz8{5c^ZbztC}Vx-AO%oi^K~f%3elL-gmA_ErnvRG*|2ewA$VV^rQMlsuPC;z&DK)68L5g=dhV}5?5%RXrzj=8i%WE;4 zZ6WVEC_}MtW4=C}?Ty;xyBA#w+uZVBVtYFOEC<tWveCP(Y~^K@!q`(Z|q2fw0-Uf+w80_NtP=~v0qx;FO~lxomSW{wIxxpw^NR{ z)1F7;<({E!tF89F2!g)vI}VHo6Tn2U57-w>0{eme!DMg%m;$B(&1E@=^}%2oI0PID z4g-gSXMiKXGr@H5Ebwe_BsdB@2PD9A!3=OTI0hUGjswSoncxI)B6uD+3Csf3U^b`$ zwV)2v1ASw74rl~TU@m9|^T2$t04xM2gHymF&;nGKHrDN+19XDL;8d^#ECr{5WuOb3 z4wi!z;Q3%BSOv}iXM(f9+29=T0`Nj`E?5m-1YQiz11|yHU=8R2y&wtJf^}d$=mQ(T zM$iv7fdP;Lo54%LAQ%F}Ky^8v^;U2JxDdPyYy;cDMd0P&72sl^uWOp`*&}cz-usiS z;Ms;zB1pERG``;uzTcox-)jl)DKT5zjy={~b5g3)91r^P_Ut%)bzI*gE@lVHe~rDT z!rqf-?*-e+e_tppE1HE-jPvW#@2Uvjor~?ga_l|tZbZ0^qSkS~aUXS2dVDF(N3En);>b^Bk)M_67OOP!Q%M`fk?j1DY%hkI(Q2b*0qlKI zgi5@~rCD+_b~-QiZF2cGb?Fuf+G2KX0Qol3bn;(fc`0Sab?Nfb2d|U7lT~pZMSGHE z`!=!VX3ui7*DA3VD@}{p<9zJvkA<&quf1aXIBXxE!H5tZ9T<`$FFb$bzJFBD9%+ek zVk`F@yyuV3bnig)^A6JTmIEk%I;Wb_qm{pf^4F)If7(ElRrXG~%cL@%|N0o^pXz)5 zYslHiJEr>J!7xt-@4qOjD0d4@F1UG`4 zz^A~?;M3qU;1=*%@HucRxD9+Bd;xqBdyee*yji{tA8t9t018UxVL(--6$P z--ADZKY~AjKLhVNfAgguA^i`q&p31ZG1C76{|1kPC%}Kef5HF2li(@vG}r+!U0EhO z{&#dA!=9iOINPaQ&SJkS?03myF?M(M-B!QdT{-XL=uocc(9Co{568GG=XV?vDkmo7 zJu4h+k9@P`D{rMZl3hHK?LA9h_!7X+6K4)32NP|nf#JbazpI}QY)_uw*OLtHYa6_9Xt=vSu`;N_$^-e`;N#qqlE3HK+^+b*0wy^(PZ&C)Xr8Q-hn_)AtK(?cbK# zv^h1995C0Oa(3T9Z))pMCi{d_&*)mFi%o6o@7ug4)xFl4$D0Js$1`i<+wt->+I{AXH0Z$ajD+*i`UZc^eu=UW+1h?eUzu=o$+dXXTEb9 z|J&UD-0aMue>BoF>zrBqcd*??s(~3qZKP-6XSZ^^l~gUi4$=*5HF2z-UpreD;iY(^ zMD#Z`Ry&1hY#kLEP5dC^(fZ%lRg9vAqexLHbVx_H(6WjmosWdK!O3;(TgW`HiLBKY zrk?Z3*Fmeb(0VoeT3n6N%zvl*Yoi6#dcDrp^w%t;)3zY_%UvDd?=z*8nxv0)qcx>{ za@o|GcM8s@B=yBQsH}5)R->B|y|qx+;r7L5jQhG_`rlTmXpi{;nxpTQb^A4kg)Y=%`%7cCKd*YSl=r;%-|+b7)d+nf;k zKarc*3HI#=qL#0F>E313@*xSaCC_Cw*ZC42sq#+K~8xyQmq$f2yITy{?8F2(A=e1lx$A8$o* z$0y|+>`kof8;~w@_FbGDNDg-QyA1Q*pHOW4TMhSR^=Q2nz7KNk0eZk%v_cP8S`8|- z@%&{ZxvECkjp^&3cI}U^zGUUow_bOt$UgV3Be&K3_Og~swmy8tFPo=a9lX`V$kBZ{PH^=SMta;sma70te)4M=6nPz9r#Wz4AQr_bekD8jD1L z5MI3fvUL>G>`C`h%?uA(RhZ+==RwN_Pkwfe1uru_1qYy4S_1g>{3M0;r*7;?_TqLCd~?`zew z_TjQDS}PJCrPl5Vp+CP&`qQCo`8I7hQ`<)ZZT{hMdx1{B3Uwt%U>QS0H)_kc%z7}? zsITqLb~JRmYbMJXkc-#IK%-%24o0=yy$(?8n%HvpYDj5FYIKj+p*q`uZn@TBV)LT5 zy84DW%qa1V5i<*o5##urp-qRgavrUMH!{hR41S}@r;_+AySs~Vy`OQq53Qx~-}A_f zMZJL>`R#{MXlED{UH&Sizk!a|>2|#q*FROqY$g(+IK*5!V<+8o7F!)`HS;rGpz#!= zd$Pul&sbfRmzwdogFai~2*(+;rQiCioDP^HrbLlnluS2PpX@$G*;?px{Z8C|JGcEZ zQMB@67_LCfp)sX(6w<3hP>gn0uaL%92u0$g0H0DFh@3(y9h}ufo{P{S*@kg=PtYYS zG&Y6LRIpV63c2WVcM_B>hejU`)c(=b#ewl^MrORaeEuyHu3m6Uz^AFHQlO_1w8N=R zAWqJ8_lc7Vg4Vh`l_F|}f8wr2)*AOn9eWgH6L$?yvmNUw?sj3`hOU{3zo;k4URnoh z#pY;{AmT4oN1>Gzd(c9%=;DvR6wMqVgDKhkN62nH%Whr12J0m>e2S2O9v)Hvqz4(x z1Y|~2zOrn>qYKMe0vVG{sbRediBhOqQlxY}DH-{)T6Ghmco=)TvjF2s4_^0hMI#wQ z1VgqXleq&`=TWx8;*GczHI%6TS~$2X>8vcC9#fd7Be58CQRO#wDz~$DiZ60(VICbt zzmrCnrk=xZ*B&oV#Zc3y1odJE-8eA;KTRGUE$=QcP99g7m(zC}86JB+%1aLL(ica~ zWpg~ZlYQhR^fOIQ7`>iVIBt;5lW`a%V>3o9_Kgw7Chc|Qt;;o^J(hqI0@%O=Oq5u za<+nD!$r5YaOI4pEMItN0GT>XjG8gwJ|otnl2p89!*VWIPSGw zt~QfM>G)V`I+a&!{)FaMMV0Q+n?C^&Bl^qZqV{=<_T}QLKd(RSo#$Wc_|C6sSfj}v zZpSv&JRI4zGx<-E?saF*yw_KOd_2gf4P+rI;NLi6BNi@e17+P&c-Epn7Y_ZBb&;0V`PkZP2*E$|m)@;`= zEMa@Tr9S%cn?1|3*}3*bFk8^v8;3O73b)(6b3TbQRo+h-kxp83=Y18q=*!si7sn-)L*3+5mNEM4>2V>9v zNV7j(IO;5a&s)UBTrH8$wvh}q<4@G%RT$f5_p1BO*FYKWdF_yk|7st#&EDeSRBDS{ zk&cRLt@qk#@id6HHhax~zJBk|>rea7_0l>%RvIW=zpw_%XKOv>pS%>O_c{*zA2K%6 ASpWb4 delta 4374 zcmcgvU2Icj7=F*%wHxiaLD!A_v2Kh3Tej>6FbD{2L1fur0xC!q#u#O$`*9seL7`m1 zg;Cs_V7M@W=#65GP_GOZ8+1spF_O$1h!7RH5k(vkF}nJ^A1m8Ag#(F+U-O;w{q=eO z-}gJ=L)P#i>*t3psbleYd^;bvxZmsDFko%gin+vE>U(T_-(-=w<{xppDrxP7SPvxmDclyUzJt^BV(=5E)wcC0k2h#)W zaT7Vxu=N_XQ61i+vi`$S4_=pDm^Wj+7vy{JBs$AknbQ}u6T=r2uL1B(bYdDF>v6JO zEw*D6z{*|$SV7w$ivaXt*3Jj|-C!(u{~wWXW}_v8im;P`4u!}0qP6V9JJU4V9mrva zc9!2uyQE7i5oq&so9w2@V)H)T3ICIIhYdB%Hvujo)@Y~Ibx0MY5HSJ z+AV-7d+t6_GwWweZleE!{ww-zblDum`}gtj7@xG%pZYYMqdED=nNN5y=HbC_$~fz8 zA&1YdW?QtBzdie6Mm`MJ0eQt#ee8~I#*Vj0w@O}m7AgqfgeZ%+C;GmenrV7UPEsph zJX^qrqgI|XJe>z}=kTkAwn+845zQ^Gv=)#8+XmncTExeGEa3&`8y>nhR609y>ijuP zJHw$1O&OZFis)0C=$!9dSf7?TzNi-ZzixGkvx_??PB}zRm`mfO!^KJuTZY%F_ZP#> z{AVruEOP@>h-e40l!uv!(>tC+$LKVMPH;YzDzEA8a?+#z1e z)sfFC2Q&`H>c+{v8!L7QNIn9;2gfc}6|t}Cnq72_#`cPZTvxf8->I(S*8>GSI#R*W zXmz>|q%Q!wVLm=%wxP+g20r-j@aGE(_|04i1eY6WaZbhQ#kT6dMcAEjG(9_Alh3Nr6 zs%*jG>%OYVa%Y>N5%ngcDY=u_3}4?=Gk<|jr5?HGBf0b=!yrv%r?X1xJ&{ulE7D&=;;Oa}6~=H$yYUR}`4 zD=uv*c$j3Zkg=OOc*Ye2>~wS3=?`Et4Y2GS@mD->_dIi$3XKmhY38Gs{e@7p4{F|} zRKEjH$-!R4IgFGnb^ep$W+~jY3at%B^m4^_oi+9IbRJY-jy5O3W%0sPRgS@#v`Jx| zVvgX_IIC8CurWFp{#RH$xeWV|EIT1+3s~(!L`vcDUNMBZ#hgHzfk45-2uKp^Q=#55 zVIiwIFbu8ZyiyM=k+BuO5R$RPla$3ZlVW8Op;U81Rs$iAo{*>p@H}{_eS&w}e}de8 zzlcNE2H&@v!y1iQqUUrK6wwOLl{-Q=dXRR&e+^|I&78zzw4NX#g>W|#gXFLf2ua?O z6fsHb>E?uN2Ce7mWeG_1smvoWXpmuwIdrxGdbS?AOZ*)9H3;sPdNF>}Q!Hck9c3J~zekB|q}5%Tx2AU>{s$ z;_mo{%3rt{>Rr6hoW?VW?Cs|zF+1NFbrpCKpaHnHRCjR?srX)6iEp4)$!=a`4qvEo zYlEcrgRxnP^+Pe|?B#%zl-{O7QtDVMBWpU44a$$!;wX-M4kZzklj%LiuwmmHASYi5=?!W|%#Y5%CN<9`7e CQYU)= diff --git a/Laptop/laptop.cpp b/Laptop/laptop.cpp index 5b4d2abe..924154f9 100644 --- a/Laptop/laptop.cpp +++ b/Laptop/laptop.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Laptop All.h" #include "HelpScreen.h" @@ -1783,6 +1784,7 @@ void HandleLapTopHandles() extern BOOLEAN gfPrintFrameBuffer; +// WANNE 2 UINT32 LaptopScreenHandle() { //User just changed modes. This is determined by the button callbacks @@ -1803,13 +1805,16 @@ UINT32 LaptopScreenHandle() } if( gfStartMapScreenToLaptopTransition ) - { //Everything is set up to start the transition animation. - SGPRect SrcRect1, SrcRect2, DstRect; - INT32 iPercentage, iScalePercentage, iFactor; - UINT32 uiStartTime, uiTimeRange, uiCurrTime; - INT32 iX, iY, iWidth, iHeight; + { + // WANNE 2: I disabled the animation of the laptop, because the screen redrawing does not work correct! - INT32 iRealPercentage; + //Everything is set up to start the transition animation. + //SGPRect SrcRect2, DstRect; + //INT32 iPercentage, iScalePercentage, iFactor; + //UINT32 uiStartTime, uiTimeRange, uiCurrTime; + //INT32 iX, iY, iWidth, iHeight; + + //INT32 iRealPercentage; SetCurrentCursorFromDatabase( VIDEO_NO_CURSOR ); //Step 1: Build the laptop image into the save buffer. @@ -1824,62 +1829,64 @@ UINT32 LaptopScreenHandle() PrintNumberOnTeam( ); ShowLights(); - //Step 2: The mapscreen image is in the EXTRABUFFER, and laptop is in the SAVEBUFFER - // Start transitioning the screen. - DstRect.iLeft = iScreenWidthOffset; //0 - DstRect.iTop = iScreenHeightOffset; //0 - DstRect.iRight = iScreenWidthOffset + 640; //640 - DstRect.iBottom = iScreenHeightOffset + 480; //480 - uiTimeRange = 1000; - iPercentage = iRealPercentage = 0; - uiStartTime = GetJA2Clock(); + //// WANNE 2 + ////Step 2: The mapscreen image is in the EXTRABUFFER, and laptop is in the SAVEBUFFER + //// Start transitioning the screen. + //DstRect.iLeft = iScreenWidthOffset; //0 + //DstRect.iTop = iScreenHeightOffset; //0 + //DstRect.iRight = iScreenWidthOffset + 640; //640 + //DstRect.iBottom = iScreenHeightOffset + 480; //480 + //uiTimeRange = 1000; + //iPercentage = iRealPercentage = 0; + //uiStartTime = GetJA2Clock(); - BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, iScreenWidthOffset, iScreenHeightOffset, - 640, 480 ); - BlitBufferToBuffer( guiEXTRABUFFER, FRAME_BUFFER, iScreenWidthOffset, iScreenHeightOffset, 640, 480 ); + //BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, iScreenWidthOffset, iScreenHeightOffset, + // 640, 480 ); + //BlitBufferToBuffer( guiEXTRABUFFER, FRAME_BUFFER, iScreenWidthOffset, iScreenHeightOffset, 640, 480 ); - PlayJA2SampleFromFile( "SOUNDS\\Laptop power up (8-11).wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN ); - while( iRealPercentage < 100 ) - { - uiCurrTime = GetJA2Clock(); - iPercentage = (uiCurrTime-uiStartTime) * 100 / uiTimeRange; - iPercentage = min( iPercentage, 100 ); + //PlayJA2SampleFromFile( "SOUNDS\\Laptop power up (8-11).wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN ); + // + //// WANNE 2 with laptop zooming + //while( iRealPercentage < 100 ) + //{ + // uiCurrTime = GetJA2Clock(); + // iPercentage = (uiCurrTime-uiStartTime) * 100 / uiTimeRange; + // iPercentage = min( iPercentage, 100 ); - iRealPercentage = iPercentage; + // iRealPercentage = iPercentage; - //Factor the percentage so that it is modified by a gravity falling acceleration effect. - iFactor = (iPercentage - 50) * 2; - if( iPercentage < 50 ) - iPercentage = (UINT32)(iPercentage + iPercentage * iFactor * 0.01 + 0.5); - else - iPercentage = (UINT32)(iPercentage + (100-iPercentage) * iFactor * 0.01 + 0.5); + // //Factor the percentage so that it is modified by a gravity falling acceleration effect. + // iFactor = (iPercentage - 50) * 2; + // if( iPercentage < 50 ) + // iPercentage = (UINT32)(iPercentage + iPercentage * iFactor * 0.01 + 0.5); + // else + // iPercentage = (UINT32)(iPercentage + (100-iPercentage) * iFactor * 0.01 + 0.5); - //Mapscreen source rect - SrcRect1.iLeft = iScreenWidthOffset + 464 * iPercentage / 100; - SrcRect1.iRight = iScreenWidthOffset + 640 - 163 * iPercentage / 100; - SrcRect1.iTop = iScreenHeightOffset + 417 * iPercentage / 100; - SrcRect1.iBottom = iScreenHeightOffset + 480 - 55 * iPercentage / 100; - //Laptop source rect - if( iPercentage < 99 ) - iScalePercentage = 10000 / (100-iPercentage); - else - iScalePercentage = 5333; - iWidth = 12 * iScalePercentage / 100; - iHeight = 9 * iScalePercentage / 100; + // //Laptop source rect + // if( iPercentage < 99 ) + // iScalePercentage = 10000 / (100-iPercentage); + // else + // iScalePercentage = 5333; + // iWidth = 12 * iScalePercentage / 100; + // iHeight = 9 * iScalePercentage / 100; - iX = iScreenWidthOffset + 472 - (472-320) * iScalePercentage / 5333; - iY = iScreenHeightOffset + 424 - (424-240) * iScalePercentage / 5333; + // iX = iScreenWidthOffset + 472 - (472-320) * iScalePercentage / 5333; + // iY = iScreenHeightOffset + 424 - (424-240) * iScalePercentage / 5333; - SrcRect2.iLeft = iX - iWidth / 2; - SrcRect2.iRight = SrcRect2.iLeft + iWidth; - SrcRect2.iTop = iY - iHeight / 2; - SrcRect2.iBottom = SrcRect2.iTop + iHeight; - - BltStretchVideoSurface( FRAME_BUFFER, guiSAVEBUFFER, 0, iScreenWidthOffset, iScreenHeightOffset, &DstRect, &SrcRect2 ); + // SrcRect2.iLeft = iX - iWidth / 2; + // SrcRect2.iRight = SrcRect2.iLeft + iWidth; + // SrcRect2.iTop = iY - iHeight / 2; + // SrcRect2.iBottom = SrcRect2.iTop + iHeight; + // + // BltStretchVideoSurface(FRAME_BUFFER, guiSAVEBUFFER, 0, 0, 0, &DstRect, &SrcRect2 ); + + // //WANNE 2 + // InvalidateScreen(); + // + // //WANNE 2 + // RefreshScreen( NULL ); + //} - InvalidateScreen(); - RefreshScreen( NULL ); - } fReDrawScreenFlag = TRUE; } @@ -1941,12 +1948,14 @@ UINT32 LaptopScreenHandle() } } } + if( fPausedReDrawScreenFlag ) { fReDrawScreenFlag = TRUE; fPausedReDrawScreenFlag = FALSE; } + // WANNE 2 if( fReDrawScreenFlag ) { RenderLapTopImage(); @@ -2075,6 +2084,7 @@ UINT32 LaptopScreenHandle() // render frame rate DisplayFrameRate( ); + // WANNE 2 // invalidate screen if redrawn if( fReDrawScreenFlag == TRUE ) { @@ -2430,11 +2440,13 @@ BOOLEAN LeaveLapTopScreen( void ) if( !gfDontStartTransitionFromLaptop ) { - SGPRect SrcRect1, SrcRect2, DstRect; - INT32 iPercentage, iScalePercentage, iFactor; - UINT32 uiStartTime, uiTimeRange, uiCurrTime; - INT32 iX, iY, iWidth, iHeight; - INT32 iRealPercentage; + // WANNE 2: I disabled the laptop animation, because the screen redrawing does not work correctly! + + //SGPRect SrcRect1, SrcRect2, DstRect; + //INT32 iPercentage, iScalePercentage, iFactor; + //UINT32 uiStartTime, uiTimeRange, uiCurrTime; + //INT32 iX, iY, iWidth, iHeight; + //INT32 iRealPercentage; gfDontStartTransitionFromLaptop = TRUE; SetCurrentCursorFromDatabase( VIDEO_NO_CURSOR ); @@ -2449,65 +2461,67 @@ BOOLEAN LeaveLapTopScreen( void ) PrintNumberOnTeam( ); ShowLights(); - //Step 2: The mapscreen image is in the EXTRABUFFER, and laptop is in the SAVEBUFFER - // Start transitioning the screen. - DstRect.iLeft = iScreenWidthOffset + 0; // 0 - DstRect.iTop = iScreenHeightOffset + 0; // 0 - DstRect.iRight = iScreenWidthOffset + 640; // 640 - DstRect.iBottom = iScreenHeightOffset + 480; // 480 - uiTimeRange = 1000; - iPercentage = iRealPercentage = 100; - uiStartTime = GetJA2Clock(); + ////Step 2: The mapscreen image is in the EXTRABUFFER, and laptop is in the SAVEBUFFER + //// Start transitioning the screen. + //DstRect.iLeft = iScreenWidthOffset + 0; // 0 + //DstRect.iTop = iScreenHeightOffset + 0; // 0 + //DstRect.iRight = iScreenWidthOffset + 640; // 640 + //DstRect.iBottom = iScreenHeightOffset + 480; // 480 + //uiTimeRange = 1000; + //iPercentage = iRealPercentage = 100; + //uiStartTime = GetJA2Clock(); - BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, iScreenWidthOffset, iScreenHeightOffset, - 640, 480 ); + //BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, iScreenWidthOffset, iScreenHeightOffset, + // 640, 480 ); - PlayJA2SampleFromFile( "SOUNDS\\Laptop power down (8-11).wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN ); - while( iRealPercentage > 0 ) - { - BlitBufferToBuffer( guiEXTRABUFFER, FRAME_BUFFER, iScreenWidthOffset, iScreenHeightOffset, 640, 480 ); + //PlayJA2SampleFromFile( "SOUNDS\\Laptop power down (8-11).wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN ); - uiCurrTime = GetJA2Clock(); - iPercentage = (uiCurrTime-uiStartTime) * 100 / uiTimeRange; - iPercentage = min( iPercentage, 100 ); - iPercentage = 100 - iPercentage; + //// WANNE 2 + //while( iRealPercentage > 0 ) + //{ + // BlitBufferToBuffer( guiEXTRABUFFER, FRAME_BUFFER, iScreenWidthOffset, iScreenHeightOffset, 640, 480 ); - iRealPercentage = iPercentage; + // uiCurrTime = GetJA2Clock(); + // iPercentage = (uiCurrTime-uiStartTime) * 100 / uiTimeRange; + // iPercentage = min( iPercentage, 100 ); + // iPercentage = 100 - iPercentage; - //Factor the percentage so that it is modified by a gravity falling acceleration effect. - iFactor = (iPercentage - 50) * 2; - if( iPercentage < 50 ) - iPercentage = (UINT32)(iPercentage + iPercentage * iFactor * 0.01 + 0.5); - else - iPercentage = (UINT32)(iPercentage + (100-iPercentage) * iFactor * 0.01 + 0.5); + // iRealPercentage = iPercentage; - //Mapscreen source rect - SrcRect1.iLeft = iScreenWidthOffset + 464 * iPercentage / 100; - SrcRect1.iRight = iScreenWidthOffset + 640 - 163 * iPercentage / 100; - SrcRect1.iTop = iScreenHeightOffset + 417 * iPercentage / 100; - SrcRect1.iBottom = iScreenHeightOffset + 480 - 55 * iPercentage / 100; - //Laptop source rect - if( iPercentage < 99 ) - iScalePercentage = 10000 / (100-iPercentage); - else - iScalePercentage = 5333; - iWidth = 12 * iScalePercentage / 100; - iHeight = 9 * iScalePercentage / 100; - iX = iScreenWidthOffset + 472 - (472-320) * iScalePercentage / 5333; - iY = iScreenHeightOffset + 424 - (424-240) * iScalePercentage / 5333; + // //Factor the percentage so that it is modified by a gravity falling acceleration effect. + // iFactor = (iPercentage - 50) * 2; + // if( iPercentage < 50 ) + // iPercentage = (UINT32)(iPercentage + iPercentage * iFactor * 0.01 + 0.5); + // else + // iPercentage = (UINT32)(iPercentage + (100-iPercentage) * iFactor * 0.01 + 0.5); - SrcRect2.iLeft = iX - iWidth / 2; - SrcRect2.iRight = SrcRect2.iLeft + iWidth; - SrcRect2.iTop = iY - iHeight / 2; - SrcRect2.iBottom = SrcRect2.iTop + iHeight; + // //Mapscreen source rect + // SrcRect1.iLeft = iScreenWidthOffset + 464 * iPercentage / 100; + // SrcRect1.iRight = iScreenWidthOffset + 640 - 163 * iPercentage / 100; + // SrcRect1.iTop = iScreenHeightOffset + 417 * iPercentage / 100; + // SrcRect1.iBottom = iScreenHeightOffset + 480 - 55 * iPercentage / 100; + // //Laptop source rect + // if( iPercentage < 99 ) + // iScalePercentage = 10000 / (100-iPercentage); + // else + // iScalePercentage = 5333; + // iWidth = 12 * iScalePercentage / 100; + // iHeight = 9 * iScalePercentage / 100; + // iX = iScreenWidthOffset + 472 - (472-320) * iScalePercentage / 5333; + // iY = iScreenHeightOffset + 424 - (424-240) * iScalePercentage / 5333; - BltStretchVideoSurface( FRAME_BUFFER, guiSAVEBUFFER, 0, iScreenWidthOffset, iScreenHeightOffset, &DstRect, &SrcRect2 ); + // SrcRect2.iLeft = iX - iWidth / 2; + // SrcRect2.iRight = SrcRect2.iLeft + iWidth; + // SrcRect2.iTop = iY - iHeight / 2; + // SrcRect2.iBottom = SrcRect2.iTop + iHeight; - InvalidateScreen(); - //gfPrintFrameBuffer = TRUE; - RefreshScreen( NULL ); - } - } + // BltStretchVideoSurface( FRAME_BUFFER, guiSAVEBUFFER, 0, 0, 0, &DstRect, &SrcRect2 ); + + // InvalidateScreen(); + // //gfPrintFrameBuffer = TRUE; + // RefreshScreen( NULL ); + //} + } } return( TRUE ); diff --git a/Laptop/mercs Account.cpp b/Laptop/mercs Account.cpp index aace4ad1..b703d2fa 100644 --- a/Laptop/mercs Account.cpp +++ b/Laptop/mercs Account.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Laptop All.h" #else @@ -515,7 +516,8 @@ UINT32 CalculateHowMuchPlayerOwesSpeck() UINT16 usMercID; - for(i=0; i<10; i++) + // WANNE 2 + for(i=0; i<14; i++) { //if it larry Roach burn advance. ( cause larry is in twice, a sober larry and a stoned larry ) if( i == MERC_LARRY_ROACHBURN ) diff --git a/Options Screen.cpp b/Options Screen.cpp index 3c2085b3..55197e43 100644 --- a/Options Screen.cpp +++ b/Options Screen.cpp @@ -275,6 +275,7 @@ UINT32 OptionsScreenHandle() HandleOptionsScreen(); + // WANNE 2 if( gfRedrawOptionsScreen ) { RenderOptionsScreen(); diff --git a/SCREENS.cpp b/SCREENS.cpp index 4187668e..915c59a2 100644 --- a/SCREENS.cpp +++ b/SCREENS.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "JA2 All.h" #else @@ -14,6 +15,9 @@ int SCREEN_HEIGHT; int iScreenWidthOffset; int iScreenHeightOffset; +// WANNE 2 +BOOLEAN fDisplayOverheadMap; + Screens GameScreens[MAX_SCREENS] = { { EditScreenInit, EditScreenHandle, EditScreenShutdown }, diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index c77eb619..f55ece0b 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -101,7 +101,6 @@ #include "Enemy Soldier Save.h" #include "BobbyRMailOrder.h" #include "Mercs.h" -#include "INIReader.h" ///////////////////////////////////////////////////// // @@ -379,6 +378,8 @@ UINT32 guiSaveGameVersion=0; //CHAR8 gsSaveGameNameWithPath[ 512 ]; +CHAR8 gSaveDir[ MAX_PATH ]; // Snap: Initilized by InitSaveDir + UINT8 gubSaveGameLoc=0; UINT32 guiScreenToGotoAfterLoadingSavedGame = 0; @@ -459,14 +460,43 @@ void HandleOldBobbyRMailOrders(); ///////////////////////////////////////////////////// +// Snap: Initializes gSaveDir global, creating the save directory if necessary +// The save directory now resides in the data directory (default or custom) +BOOLEAN InitSaveDir() +{ + // Look for a custom data dir first + std::string dataDir = gCustomDataCat.GetRootDir(); + if( dataDir.empty() || FileGetAttributes( (STR) dataDir.c_str() ) == 0xFFFFFFFF ) { + dataDir = gDefaultDataCat.GetRootDir(); + } + + // The locale-specific save dir location is of the form L"..\\SavedGames" + // This has not changed; instead, we strip the ".." at the beginning + sprintf( (char *) gSaveDir, "%s%S", dataDir.c_str(), pMessageStrings[ MSG_SAVEDIRECTORY ] + 2 ); + + // This was moved here from SaveGame + //Check to see if the save directory exists + if( FileGetAttributes( (STR) gSaveDir ) == 0xFFFFFFFF ) + { + //ok the direcotry doesnt exist, create it + if( !MakeFileManDirectory( (CHAR8 *)gSaveDir ) ) + { + return FALSE; + } + } + + return TRUE; +} + + BOOLEAN SaveGame( UINT8 ubSaveGameID, STR16 pGameDesc ) { UINT32 uiNumBytesWritten=0; HWFILE hFile=0; SAVED_GAME_HEADER SaveGameHeader; - CHAR8 zSaveGameName[ 512 ]; + CHAR8 zSaveGameName[ MAX_PATH ]; UINT32 uiSizeOfGeneralInfo = sizeof( GENERAL_SAVE_INFO ); - UINT8 saveDir[100]; + //UINT8 saveDir[100]; BOOLEAN fPausedStateBeforeSaving = gfGamePaused; BOOLEAN fLockPauseStateBeforeSaving = gfLockPauseState; INT32 iSaveLoadGameMessageBoxID = -1; @@ -474,10 +504,12 @@ BOOLEAN SaveGame( UINT8 ubSaveGameID, STR16 pGameDesc ) BOOLEAN fWePausedIt = FALSE; - sprintf( (char *) saveDir, "%S", pMessageStrings[ MSG_SAVEDIRECTORY ] ); + //sprintf( (char *) saveDir, "%S", pMessageStrings[ MSG_SAVEDIRECTORY ] ); #ifdef JA2BETAVERSION #ifndef CRIPPLED_VERSION + //AssertMsg( uiSizeOfGeneralInfo == 1024, String( "Saved General info is NOT 1024, it is %d. DF 1.", uiSizeOfGeneralInfo ) ); + //AssertMsg( sizeof( LaptopSaveInfoStruct ) == 7440, String( "LaptopSaveStruct is NOT 7440, it is %d. DF 1.", sizeof( LaptopSaveInfoStruct ) ) ); #endif #endif @@ -579,14 +611,14 @@ BOOLEAN SaveGame( UINT8 ubSaveGameID, STR16 pGameDesc ) wcscpy( pGameDesc, pMessageStrings[ MSG_NODESC ] ); //Check to see if the save directory exists - if( FileGetAttributes( (STR) saveDir ) == 0xFFFFFFFF ) + /*if( FileGetAttributes( (STR) saveDir ) == 0xFFFFFFFF ) { //ok the direcotry doesnt exist, create it if( !MakeFileManDirectory( (CHAR8 *)saveDir ) ) { goto FAILED_TO_SAVE; } - } + }*/ //Create the name of the file CreateSavedGameFileNameFromNumber( ubSaveGameID, zSaveGameName ); @@ -1351,7 +1383,7 @@ BOOLEAN LoadSavedGame( UINT8 ubSavedGameID ) INT16 sLoadSectorX; INT16 sLoadSectorY; INT8 bLoadSectorZ; - CHAR8 zSaveGameName[ 512 ]; + CHAR8 zSaveGameName[ MAX_PATH ]; UINT32 uiSizeOfGeneralInfo = sizeof( GENERAL_SAVE_INFO ); UINT32 uiRelStartPerc; @@ -4034,19 +4066,19 @@ void CreateSavedGameFileNameFromNumber( UINT8 ubSaveGameID, STR pzNewFileName ) { //if we are loading a game, and the user hasnt saved any consecutinve saves, load the defualt save if( guiCurrentQuickSaveNumber == 0 ) - sprintf( pzNewFileName , "%S\\%S.%S", pMessageStrings[ MSG_SAVEDIRECTORY ], pMessageStrings[ MSG_QUICKSAVE_NAME ], pMessageStrings[ MSG_SAVEEXTENSION ] ); + sprintf( pzNewFileName , "%s\\%S.%S", gSaveDir, pMessageStrings[ MSG_QUICKSAVE_NAME ], pMessageStrings[ MSG_SAVEEXTENSION ] ); else - sprintf( pzNewFileName , "%S\\%S%02d.%S", pMessageStrings[ MSG_SAVEDIRECTORY ], pMessageStrings[ MSG_QUICKSAVE_NAME ], guiCurrentQuickSaveNumber, pMessageStrings[ MSG_SAVEEXTENSION ] ); + sprintf( pzNewFileName , "%s\\%S%02d.%S", gSaveDir, pMessageStrings[ MSG_QUICKSAVE_NAME ], guiCurrentQuickSaveNumber, pMessageStrings[ MSG_SAVEEXTENSION ] ); } else #endif - sprintf( pzNewFileName , "%S\\%S.%S", pMessageStrings[ MSG_SAVEDIRECTORY ], pMessageStrings[ MSG_QUICKSAVE_NAME ], pMessageStrings[ MSG_SAVEEXTENSION ] ); + sprintf( pzNewFileName , "%s\\%S.%S", gSaveDir, pMessageStrings[ MSG_QUICKSAVE_NAME ], pMessageStrings[ MSG_SAVEEXTENSION ] ); } //#ifdef JA2BETAVERSION else if( ubSaveGameID == SAVE__END_TURN_NUM ) { //The name of the file - sprintf( pzNewFileName , "%S\\Auto%02d.%S", pMessageStrings[ MSG_SAVEDIRECTORY ], guiLastSaveGameNum, pMessageStrings[ MSG_SAVEEXTENSION ] ); + sprintf( pzNewFileName , "%s\\Auto%02d.%S", gSaveDir, guiLastSaveGameNum, pMessageStrings[ MSG_SAVEEXTENSION ] ); //increment end turn number guiLastSaveGameNum++; @@ -4060,7 +4092,7 @@ void CreateSavedGameFileNameFromNumber( UINT8 ubSaveGameID, STR pzNewFileName ) //#endif else - sprintf( pzNewFileName , "%S\\%S%02d.%S", pMessageStrings[ MSG_SAVEDIRECTORY ], pMessageStrings[ MSG_SAVE_NAME ], ubSaveGameID, pMessageStrings[ MSG_SAVEEXTENSION ] ); + sprintf( pzNewFileName , "%s\\%S%02d.%S", gSaveDir, pMessageStrings[ MSG_SAVE_NAME ], ubSaveGameID, pMessageStrings[ MSG_SAVEEXTENSION ] ); } @@ -4196,9 +4228,9 @@ BOOLEAN LoadMercPathToSoldierStruct( HWFILE hFile, UINT8 ubID ) #ifdef JA2BETAVERSION void InitSaveGameFilePosition() { - CHAR8 zFileName[128]; + CHAR8 zFileName[ MAX_PATH ]; - sprintf( zFileName, "%S\\SaveGameFilePos%2d.txt", pMessageStrings[ MSG_SAVEDIRECTORY ], gubSaveGameLoc ); + sprintf( zFileName, "%s\\SaveGameFilePos%2d.txt", gSaveDir, gubSaveGameLoc ); FileDelete( zFileName ); } @@ -4209,9 +4241,9 @@ void SaveGameFilePosition( INT32 iPos, STR pMsg ) CHAR8 zTempString[512]; UINT32 uiNumBytesWritten; UINT32 uiStrLen=0; - CHAR8 zFileName[128]; + CHAR8 zFileName[MAX_PATH]; - sprintf( zFileName, "%S\\SaveGameFilePos%2d.txt", pMessageStrings[ MSG_SAVEDIRECTORY ], gubSaveGameLoc ); + sprintf( zFileName, "%s\\SaveGameFilePos%2d.txt", gSaveDir, gubSaveGameLoc ); // create the save game file hFile = FileOpen( zFileName, FILE_ACCESS_WRITE | FILE_OPEN_ALWAYS, FALSE ); @@ -4240,9 +4272,9 @@ void SaveGameFilePosition( INT32 iPos, STR pMsg ) void InitLoadGameFilePosition() { - CHAR8 zFileName[128]; + CHAR8 zFileName[MAX_PATH]; - sprintf( zFileName, "%S\\LoadGameFilePos%2d.txt", pMessageStrings[ MSG_SAVEDIRECTORY ], gubSaveGameLoc ); + sprintf( zFileName, "%s\\LoadGameFilePos%2d.txt", gSaveDir, gubSaveGameLoc ); FileDelete( zFileName ); } @@ -4253,9 +4285,9 @@ void LoadGameFilePosition( INT32 iPos, STR pMsg ) UINT32 uiNumBytesWritten; UINT32 uiStrLen=0; - CHAR8 zFileName[128]; + CHAR8 zFileName[MAX_PATH]; - sprintf( zFileName, "%S\\LoadGameFilePos%2d.txt", pMessageStrings[ MSG_SAVEDIRECTORY ], gubSaveGameLoc ); + sprintf( zFileName, "%s\\LoadGameFilePos%2d.txt", gSaveDir, gubSaveGameLoc ); // create the save game file hFile = FileOpen( zFileName, FILE_ACCESS_WRITE | FILE_OPEN_ALWAYS, FALSE ); @@ -4862,7 +4894,7 @@ BOOLEAN DoesUserHaveEnoughHardDriveSpace() void InitShutDownMapTempFileTest( BOOLEAN fInit, STR pNameOfFile, UINT8 ubSaveGameID ) { - CHAR8 zFileName[128]; + CHAR8 zFileName[MAX_PATH]; HWFILE hFile; CHAR8 zTempString[512]; UINT32 uiStrLen; @@ -4871,7 +4903,7 @@ void InitShutDownMapTempFileTest( BOOLEAN fInit, STR pNameOfFile, UINT8 ubSaveGa //strcpy( gzNameOfMapTempFile, pNameOfFile); sprintf( gzNameOfMapTempFile, "%s%d", pNameOfFile, ubSaveGameID ); - sprintf( zFileName, "%S\\%s.txt", pMessageStrings[ MSG_SAVEDIRECTORY ], gzNameOfMapTempFile ); + sprintf( zFileName, "%s\\%s.txt", gSaveDir, gzNameOfMapTempFile ); if( fInit ) { @@ -4917,11 +4949,11 @@ void WriteTempFileNameToFile( STR pFileName, UINT32 uiSizeOfFile, HFILE hSaveFil UINT32 uiNumBytesWritten; UINT32 uiStrLen=0; - CHAR8 zFileName[128]; + CHAR8 zFileName[MAX_PATH]; guiSizeOfTempFiles += uiSizeOfFile; - sprintf( zFileName, "%S\\%s.txt", pMessageStrings[ MSG_SAVEDIRECTORY ], gzNameOfMapTempFile ); + sprintf( zFileName, "%s\\%s.txt", gSaveDir, gzNameOfMapTempFile ); // create the save game file hFile = FileOpen( zFileName, FILE_ACCESS_WRITE | FILE_OPEN_ALWAYS, FALSE ); @@ -5054,9 +5086,7 @@ void TruncateStrategicGroupSizes() SECTORINFO *pSector; INT32 i; - //Kaiden: Loading INI file to read Values... - CIniReader iniReader("..\\Ja2_Options.ini"); - INT32 iMaxEnemyGroupSize = iniReader.ReadInteger("Options","MAX_STRATEGIC_TEAM_SIZE",20); + INT32 iMaxEnemyGroupSize = gGameExternalOptions.iMaxEnemyGroupSize; for( i = SEC_A1; i < SEC_P16; i++ ) @@ -5242,8 +5272,8 @@ void UpdateMercMercContractInfo() INT8 GetNumberForAutoSave( BOOLEAN fLatestAutoSave ) { - CHAR zFileName1[256]; - CHAR zFileName2[256]; + CHAR zFileName1[MAX_PATH]; + CHAR zFileName2[MAX_PATH]; HWFILE hFile; BOOLEAN fFile1Exist, fFile2Exist; SGP_FILETIME CreationTime1, LastAccessedTime1, LastWriteTime1; @@ -5254,8 +5284,8 @@ INT8 GetNumberForAutoSave( BOOLEAN fLatestAutoSave ) //The name of the file - sprintf( zFileName1, "%S\\Auto%02d.%S", pMessageStrings[ MSG_SAVEDIRECTORY ], 0, pMessageStrings[ MSG_SAVEEXTENSION ] ); - sprintf( zFileName2, "%S\\Auto%02d.%S", pMessageStrings[ MSG_SAVEDIRECTORY ], 1, pMessageStrings[ MSG_SAVEEXTENSION ] ); + sprintf( zFileName1, "%s\\Auto%02d.%S", gSaveDir, 0, pMessageStrings[ MSG_SAVEEXTENSION ] ); + sprintf( zFileName2, "%s\\Auto%02d.%S", gSaveDir, 1, pMessageStrings[ MSG_SAVEEXTENSION ] ); if( FileExists( zFileName1 ) ) { @@ -5424,4 +5454,4 @@ UINT32 CalcJA2EncryptionSet( SAVED_GAME_HEADER * pSaveGameHeader ) } return( uiEncryptionSet ); -} \ No newline at end of file +} diff --git a/SaveLoadGame.h b/SaveLoadGame.h index 0d128e75..c4ad6593 100644 --- a/SaveLoadGame.h +++ b/SaveLoadGame.h @@ -54,14 +54,13 @@ typedef struct } SAVED_GAME_HEADER; - extern UINT32 guiScreenToGotoAfterLoadingSavedGame; extern UINT32 guiSaveGameVersion; void CreateSavedGameFileNameFromNumber( UINT8 ubSaveGameID, STR pzNewFileName ); - +BOOLEAN InitSaveDir(); BOOLEAN SaveGame( UINT8 ubSaveGameID, STR16 pGameDesc ); BOOLEAN LoadSavedGame( UINT8 ubSavedGameID ); diff --git a/Standard Gaming Platform/Button System.cpp b/Standard Gaming Platform/Button System.cpp index 2ec4f4b2..db463e24 100644 --- a/Standard Gaming Platform/Button System.cpp +++ b/Standard Gaming Platform/Button System.cpp @@ -1658,6 +1658,7 @@ INT32 CreateIconButton(INT16 Icon,INT16 IconIndex,INT16 GenImg,INT16 xloc,INT16 b->BackRect = -1; #endif + // WANNE 2 // Add button to the button list #ifdef BUTTONSYSTEM_DEBUGGING AssertFailIfIdenticalButtonAttributesFound( b ); @@ -4160,6 +4161,7 @@ void BtnGenericMouseMoveButtonCallback(GUI_BUTTON *btn,INT32 reason) PlayButtonSound( btn->IDNum, BUTTON_SOUND_CLICKED_OFF ); } } + #ifdef JA2 InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY); #endif @@ -4171,6 +4173,7 @@ void BtnGenericMouseMoveButtonCallback(GUI_BUTTON *btn,INT32 reason) { PlayButtonSound( btn->IDNum, BUTTON_SOUND_CLICKED_ON ); } + #ifdef JA2 InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY); #endif diff --git a/Standard Gaming Platform/video.cpp b/Standard Gaming Platform/video.cpp index 8353cbe7..2e6c1a73 100644 --- a/Standard Gaming Platform/video.cpp +++ b/Standard Gaming Platform/video.cpp @@ -772,6 +772,7 @@ BOOLEAN CanBlitToMouseBuffer(void) void InvalidateRegion(INT32 iLeft, INT32 iTop, INT32 iRight, INT32 iBottom) { + // WANNE 2 if (gfForceFullScreenRefresh == TRUE) { // diff --git a/Strategic/Assignments.cpp b/Strategic/Assignments.cpp index 53e28491..13655d01 100644 --- a/Strategic/Assignments.cpp +++ b/Strategic/Assignments.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #include "GameSettings.h" @@ -8589,6 +8590,7 @@ BOOLEAN CreateDestroyAssignmentPopUpBoxes( void ) // these boxes are always created while in mapscreen... CreateEPCBox( ); + // WANNE 2 CreateAssignmentsBox( ); CreateTrainingBox( ); CreateAttributeBox(); @@ -8745,16 +8747,19 @@ void SetTacticalPopUpAssignmentBoxXY( void ) gsAssignmentBoxesY = sY; + // WANNE 2 // ATE: Check if we are past tactical viewport.... // Use estimate width's/heights - if ( ( gsAssignmentBoxesX + 100 ) > 640 ) + if ( ( gsAssignmentBoxesX + 100 ) > SCREEN_WIDTH ) { - gsAssignmentBoxesX = 540; + //gsAssignmentBoxesX = 540; + gsAssignmentBoxesX = SCREEN_WIDTH - 100; } - if ( ( gsAssignmentBoxesY + 130 ) > 320 ) + // WANNE 2 + if ( ( gsAssignmentBoxesY + 130 ) > (SCREEN_HEIGHT - 160) ) { - gsAssignmentBoxesY = 190; + gsAssignmentBoxesY = SCREEN_HEIGHT - 290; } return; @@ -8823,9 +8828,10 @@ void CheckAndUpdateTacticalAssignmentPopUpPositions( void ) { GetBoxSize( ghRepairBox, &pDimensions ); - if( gsAssignmentBoxesX + pDimensions2.iRight + pDimensions.iRight >= 640 ) + // WANNE 2 + if( gsAssignmentBoxesX + pDimensions2.iRight + pDimensions.iRight >= SCREEN_WIDTH ) { - gsAssignmentBoxesX = ( INT16 ) ( 639 - ( pDimensions2.iRight + pDimensions.iRight ) ); + gsAssignmentBoxesX = ( INT16 ) ( (SCREEN_WIDTH - 1) - ( pDimensions2.iRight + pDimensions.iRight ) ); SetRenderFlags( RENDER_FLAG_FULL ); } @@ -8838,9 +8844,10 @@ void CheckAndUpdateTacticalAssignmentPopUpPositions( void ) sLongest = ( INT16 )pDimensions.iBottom + ( ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_REPAIR ); } - if( gsAssignmentBoxesY + sLongest >= 360 ) + // WANNE 2 + if( gsAssignmentBoxesY + sLongest >= (SCREEN_HEIGHT - 120) ) { - gsAssignmentBoxesY = ( INT16 )( 359 - ( sLongest ) ); + gsAssignmentBoxesY = ( INT16 )( (SCREEN_HEIGHT - 121) - ( sLongest ) ); SetRenderFlags( RENDER_FLAG_FULL ); } @@ -8854,9 +8861,9 @@ void CheckAndUpdateTacticalAssignmentPopUpPositions( void ) GetBoxSize( ghSquadBox, &pDimensions ); - if( gsAssignmentBoxesX + pDimensions2.iRight + pDimensions.iRight >= 640 ) + if( gsAssignmentBoxesX + pDimensions2.iRight + pDimensions.iRight >= SCREEN_WIDTH ) { - gsAssignmentBoxesX = ( INT16 ) ( 639 - ( pDimensions2.iRight + pDimensions.iRight ) ); + gsAssignmentBoxesX = ( INT16 ) ( (SCREEN_WIDTH - 1) - ( pDimensions2.iRight + pDimensions.iRight ) ); SetRenderFlags( RENDER_FLAG_FULL ); } @@ -8869,9 +8876,10 @@ void CheckAndUpdateTacticalAssignmentPopUpPositions( void ) sLongest = ( INT16 )pDimensions.iBottom; } - if( gsAssignmentBoxesY + sLongest >= 360 ) + // WANNE 2 + if( gsAssignmentBoxesY + sLongest >= (SCREEN_HEIGHT - 120) ) { - gsAssignmentBoxesY = ( INT16 )( 359 - ( sLongest ) ); + gsAssignmentBoxesY = ( INT16 )( (SCREEN_HEIGHT - 121) - ( sLongest ) ); SetRenderFlags( RENDER_FLAG_FULL ); } @@ -8885,15 +8893,17 @@ void CheckAndUpdateTacticalAssignmentPopUpPositions( void ) GetBoxSize( ghTrainingBox, &pDimensions ); GetBoxSize( ghAttributeBox, &pDimensions3 ); - if( gsAssignmentBoxesX + pDimensions2.iRight + pDimensions.iRight + pDimensions3.iRight >= 640 ) + // WANNE 2 + if( gsAssignmentBoxesX + pDimensions2.iRight + pDimensions.iRight + pDimensions3.iRight >= SCREEN_WIDTH ) { - gsAssignmentBoxesX = ( INT16 ) ( 639 - ( pDimensions2.iRight + pDimensions.iRight + pDimensions3.iRight ) ); + gsAssignmentBoxesX = ( INT16 ) ( (SCREEN_WIDTH - 1) - ( pDimensions2.iRight + pDimensions.iRight + pDimensions3.iRight ) ); SetRenderFlags( RENDER_FLAG_FULL ); } - if( gsAssignmentBoxesY + pDimensions3.iBottom + ( GetFontHeight( MAP_SCREEN_FONT ) * ASSIGN_MENU_TRAIN ) >= 360 ) + // WANNE 2 + if( gsAssignmentBoxesY + pDimensions3.iBottom + ( GetFontHeight( MAP_SCREEN_FONT ) * ASSIGN_MENU_TRAIN ) >= (SCREEN_HEIGHT - 120) ) { - gsAssignmentBoxesY = ( INT16 )( 359 - ( pDimensions3.iBottom ) ); + gsAssignmentBoxesY = ( INT16 )( (SCREEN_HEIGHT - 121) - ( pDimensions3.iBottom ) ); SetRenderFlags( RENDER_FLAG_FULL ); } @@ -8916,15 +8926,17 @@ void CheckAndUpdateTacticalAssignmentPopUpPositions( void ) { GetBoxSize( ghTrainingBox, &pDimensions ); - if( gsAssignmentBoxesX + pDimensions2.iRight + pDimensions.iRight >= 640 ) + // WANNE 2 + if( gsAssignmentBoxesX + pDimensions2.iRight + pDimensions.iRight >= SCREEN_WIDTH ) { - gsAssignmentBoxesX = ( INT16 ) ( 639 - ( pDimensions2.iRight + pDimensions.iRight ) ); + gsAssignmentBoxesX = ( INT16 ) ( (SCREEN_WIDTH - 1) - ( pDimensions2.iRight + pDimensions.iRight ) ); SetRenderFlags( RENDER_FLAG_FULL ); } - if( gsAssignmentBoxesY + pDimensions2.iBottom + ( ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_TRAIN ) >= 360 ) + // WANNE 2 + if( gsAssignmentBoxesY + pDimensions2.iBottom + ( ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_TRAIN ) >= (SCREEN_HEIGHT - 120) ) { - gsAssignmentBoxesY = ( INT16 )( 359 - ( pDimensions2.iBottom ) - ( ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_TRAIN ) ); + gsAssignmentBoxesY = ( INT16 )( (SCREEN_HEIGHT - 121) - ( pDimensions2.iBottom ) - ( ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_TRAIN ) ); SetRenderFlags( RENDER_FLAG_FULL ); } @@ -8938,16 +8950,17 @@ void CheckAndUpdateTacticalAssignmentPopUpPositions( void ) } else { + // WANNE 2 // just the assignment box - if( gsAssignmentBoxesX + pDimensions2.iRight >= 640 ) + if( gsAssignmentBoxesX + pDimensions2.iRight >= SCREEN_WIDTH ) { - gsAssignmentBoxesX = ( INT16 ) ( 639 - ( pDimensions2.iRight ) ); + gsAssignmentBoxesX = ( INT16 ) ( (SCREEN_WIDTH - 1) - ( pDimensions2.iRight ) ); SetRenderFlags( RENDER_FLAG_FULL ); } - if( gsAssignmentBoxesY + pDimensions2.iBottom >= 360 ) + if( gsAssignmentBoxesY + pDimensions2.iBottom >= (SCREEN_HEIGHT - 120) ) { - gsAssignmentBoxesY = ( INT16 )( 359 - ( pDimensions2.iBottom ) ); + gsAssignmentBoxesY = ( INT16 )( (SCREEN_HEIGHT - 121) - ( pDimensions2.iBottom ) ); SetRenderFlags( RENDER_FLAG_FULL ); } @@ -8984,9 +8997,10 @@ void PositionCursorForTacticalAssignmentBox( void ) iFontHeight = GetLineSpace( ghAssignmentBox ) + GetFontHeight( GetBoxFont( ghAssignmentBox ) ); + // WANNE 2 if( gGameSettings.fOptions[ TOPTION_DONT_MOVE_MOUSE ] == FALSE ) { - SimulateMouseMovement( pPosition.iX + pDimensions.iRight - 6, pPosition.iY + ( iFontHeight / 2 ) + 2 ); + //SimulateMouseMovement( pPosition.iX + pDimensions.iRight - 6, pPosition.iY + ( iFontHeight / 2 ) + 2 ); } } @@ -10557,6 +10571,7 @@ void RebuildAssignmentsBox( void ) ghAssignmentBox = -1; } + // WANNE 2 CreateAssignmentsBox( ); } diff --git a/Strategic/Auto Resolve.cpp b/Strategic/Auto Resolve.cpp index 0e2d507f..9910efbe 100644 --- a/Strategic/Auto Resolve.cpp +++ b/Strategic/Auto Resolve.cpp @@ -1,3 +1,5 @@ +// WANNE 2 +// MAXIMUM NUMBER OF ENEMIES: 32 #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #include "GameSettings.h" @@ -506,7 +508,7 @@ void DoTransitionFromPreBattleInterfaceToAutoResolve() sEndTop = SrcRect.iTop + gpAR->sHeight / 2; //save the prebattle/mapscreen interface background - BlitBufferToBuffer( FRAME_BUFFER, guiEXTRABUFFER, 0, 0, 640, 480 ); + BlitBufferToBuffer( FRAME_BUFFER, guiEXTRABUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); //render the autoresolve panel RenderAutoResolve(); @@ -644,12 +646,16 @@ UINT32 AutoResolveScreenHandle() //Take the framebuffer, shade it, and save it to the SAVEBUFFER. ClipRect.iLeft = 0; ClipRect.iTop = 0; - ClipRect.iRight = 640; - ClipRect.iBottom = 480; + /*ClipRect.iRight = 640; + ClipRect.iBottom = 480;*/ + ClipRect.iRight = SCREEN_WIDTH; + ClipRect.iBottom = SCREEN_HEIGHT; + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); Blt16BPPBufferShadowRect( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect ); UnLockVideoSurface( FRAME_BUFFER ); - BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 0, 0, 640, 480 ); + //BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 0, 0, 640, 480 ); + BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); KillPreBattleInterface(); CalculateAutoResolveInfo(); CalculateSoldierCells( FALSE ); @@ -658,7 +664,9 @@ UINT32 AutoResolveScreenHandle() DetermineTeamLeader( FALSE ); //enemy team CalculateAttackValues(); if( gfExtraBuffer ) + { DoTransitionFromPreBattleInterfaceToAutoResolve(); + } else gpAR->fExpanding = TRUE; gpAR->fRenderAutoResolve = TRUE; @@ -826,8 +834,9 @@ void CalculateSoldierCells( BOOLEAN fReset ) } gpAR->uiTimeSlice = gpAR->uiTimeSlice * gpAR->ubTimeModifierPercentage / 100; - iTop = 240 - gpAR->sHeight/2; - if( iTop > 120 ) + // WANNE 2 + iTop = iScreenHeightOffset + (240 - gpAR->sHeight/2); + if( iTop > (iScreenHeightOffset + 120) ) iTop -= 40; if( gpAR->ubMercs ) @@ -843,6 +852,7 @@ void CalculateSoldierCells( BOOLEAN fReset ) if( y >= gapStartRow ) index -= y - gapStartRow + 1; Assert( index >= 0 && index < gpAR->ubMercs ); + gpMercs[ index ].xp = gpAR->sCenterStartX + 3 - 55*(x+1); gpMercs[ index ].yp = iStartY + y*47; gpMercs[ index ].uiFlags = CELL_MERC; @@ -1047,15 +1057,16 @@ void BuildInterfaceBuffer() INT32 x,y; //Setup the blitting clip regions, so we don't draw outside of the region (for excess panelling) - gpAR->Rect.iLeft = 320 - gpAR->sWidth/2; + // WANNE 2 + gpAR->Rect.iLeft = iScreenWidthOffset + (320 - gpAR->sWidth/2); gpAR->Rect.iRight = gpAR->Rect.iLeft + gpAR->sWidth; - gpAR->Rect.iTop = 240 - gpAR->sHeight/2; - if( gpAR->Rect.iTop > 120 ) + gpAR->Rect.iTop = iScreenHeightOffset + (240 - gpAR->sHeight/2); + if( gpAR->Rect.iTop > (iScreenHeightOffset + 120) ) gpAR->Rect.iTop -= 40; gpAR->Rect.iBottom = gpAR->Rect.iTop + gpAR->sHeight; DestRect.iLeft = 0; - DestRect.iTop = 0; + DestRect.iTop = 0; DestRect.iRight = gpAR->sWidth; DestRect.iBottom = gpAR->sHeight; @@ -1200,7 +1211,7 @@ void ExpandWindow() //The new rect now determines the state of the current rectangle. pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); - SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, 640, 480 ); + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); RectangleDraw( TRUE, gpAR->ExRect.iLeft, gpAR->ExRect.iTop, gpAR->ExRect.iRight, gpAR->ExRect.iBottom, Get16BPPColor( FROMRGB( 200, 200, 100 ) ), pDestBuf ); UnLockVideoSurface( FRAME_BUFFER ); //left @@ -1623,7 +1634,8 @@ void RenderAutoResolve() if( gpAR->fPendingSurrender ) { - DisplayWrappedString( (UINT16)(gpAR->sCenterStartX+16), (UINT16)(230+gpAR->bVerticalOffset), 108, 2, + // WANNE 2 + DisplayWrappedString( (UINT16)(gpAR->sCenterStartX+16), (UINT16)(iScreenHeightOffset + 230+gpAR->bVerticalOffset), 108, 2, (UINT8)FONT10ARIAL, FONT_YELLOW, gpStrategicString[ STR_ENEMY_SURRENDER_OFFER ], FONT_BLACK, FALSE, LEFT_JUSTIFIED ); } @@ -1727,7 +1739,7 @@ void RenderAutoResolve() } else { - DisplayWrappedString( (UINT16)(gpAR->sCenterStartX+16), 310, 108, 2, + DisplayWrappedString( (UINT16)(gpAR->sCenterStartX+16), iScreenHeightOffset + 310, 108, 2, FONT10ARIAL, FONT_YELLOW, gpStrategicString[ STR_ENEMY_CAPTURED ], FONT_BLACK, FALSE, LEFT_JUSTIFIED ); swprintf( str, gpStrategicString[ STR_AR_OVER_CAPTURED ] ); } @@ -1743,12 +1755,13 @@ void RenderAutoResolve() break; } //Render the results of the battle. + // WANNE 2 SetFont( BLOCKFONT2 ); xp = gpAR->sCenterStartX + 12; - yp = 218 + gpAR->bVerticalOffset; + yp = iScreenHeightOffset + 218 + gpAR->bVerticalOffset; BltVideoObjectFromIndex( FRAME_BUFFER, gpAR->iIndent, 0, xp, yp, VO_BLT_SRCTRANSPARENCY, NULL ); xp = gpAR->sCenterStartX + 70 - StringPixLength( str, BLOCKFONT2 )/2; - yp = 227 + gpAR->bVerticalOffset; + yp = iScreenHeightOffset + 227 + gpAR->bVerticalOffset; mprintf( xp, yp, str ); //Render the total battle time elapsed. @@ -1758,7 +1771,8 @@ void RenderAutoResolve() gpAR->uiTotalElapsedBattleTimeInMilliseconds/60000, (gpAR->uiTotalElapsedBattleTimeInMilliseconds%60000)/1000 ); xp = gpAR->sCenterStartX + 70 - StringPixLength( str, FONT10ARIAL )/2; - yp = 290 + gpAR->bVerticalOffset; + // WANNE 2 + yp = iScreenHeightOffset + 290 + gpAR->bVerticalOffset; SetFontForeground( FONT_YELLOW ); mprintf( xp, yp, str ); } @@ -1774,7 +1788,7 @@ void CreateAutoResolveInterface() HVOBJECT hVObject; UINT8 ubGreenMilitia, ubRegMilitia, ubEliteMilitia; //Setup new autoresolve blanket interface. - MSYS_DefineRegion( &gpAR->AutoResolveRegion, 0, 0, 640, 480, MSYS_PRIORITY_HIGH-1, 0, + MSYS_DefineRegion( &gpAR->AutoResolveRegion, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGH-1, 0, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK ); gpAR->fRenderAutoResolve = TRUE; gpAR->fExitAutoResolve = FALSE; @@ -2018,28 +2032,30 @@ void CreateAutoResolveInterface() //Build the interface buffer, and blit the "shaded" background. This info won't //change from now on, but will be used to restore text. BuildInterfaceBuffer(); - BlitBufferToBuffer( guiSAVEBUFFER, FRAME_BUFFER, 0, 0, 640, 480 ); + BlitBufferToBuffer( guiSAVEBUFFER, FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); //If we are bumping up the interface, then also use that piece of info to //move the buttons up by the same amount. - gpAR->bVerticalOffset = 240 - gpAR->sHeight/2 > 120 ? -40 : 0; + + gpAR->bVerticalOffset = (240 - gpAR->sHeight/2) > 120 ? -40 : 0; + // WANNE 2 //Create the buttons -- subject to relocation gpAR->iButton[ PLAY_BUTTON ] = - QuickCreateButton( gpAR->iButtonImage[ PLAY_BUTTON ] , (INT16)(gpAR->sCenterStartX+11), (INT16)(240+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, + QuickCreateButton( gpAR->iButtonImage[ PLAY_BUTTON ] , (INT16)(gpAR->sCenterStartX+11), (INT16)(iScreenHeightOffset + 240+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, PlayButtonCallback ); gpAR->iButton[ FAST_BUTTON ] = - QuickCreateButton( gpAR->iButtonImage[ FAST_BUTTON ] , (INT16)(gpAR->sCenterStartX+51), (INT16)(240+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, + QuickCreateButton( gpAR->iButtonImage[ FAST_BUTTON ] , (INT16)(gpAR->sCenterStartX+51), (INT16)(iScreenHeightOffset + 240+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, FastButtonCallback ); gpAR->iButton[ FINISH_BUTTON ] = - QuickCreateButton( gpAR->iButtonImage[ FINISH_BUTTON ] , (INT16)(gpAR->sCenterStartX+91), (INT16)(240+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, + QuickCreateButton( gpAR->iButtonImage[ FINISH_BUTTON ] , (INT16)(gpAR->sCenterStartX+91), (INT16)(iScreenHeightOffset + 240+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, FinishButtonCallback ); gpAR->iButton[ PAUSE_BUTTON ] = - QuickCreateButton( gpAR->iButtonImage[ PAUSE_BUTTON ] , (INT16)(gpAR->sCenterStartX+11), (INT16)(274+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, + QuickCreateButton( gpAR->iButtonImage[ PAUSE_BUTTON ] , (INT16)(gpAR->sCenterStartX+11), (INT16)(iScreenHeightOffset + 274+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, PauseButtonCallback ); gpAR->iButton[ RETREAT_BUTTON ] = - QuickCreateButton( gpAR->iButtonImage[ RETREAT_BUTTON ], (INT16)(gpAR->sCenterStartX+51), (INT16)(274+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, + QuickCreateButton( gpAR->iButtonImage[ RETREAT_BUTTON ], (INT16)(gpAR->sCenterStartX+51), (INT16)(iScreenHeightOffset + 274+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, RetreatButtonCallback ); if( !gpAR->ubMercs ) { @@ -2048,23 +2064,23 @@ void CreateAutoResolveInterface() SpecifyGeneralButtonTextAttributes( gpAR->iButton[ RETREAT_BUTTON ], gpStrategicString[STR_AR_RETREAT_BUTTON], BLOCKFONT2, 169, FONT_NEARBLACK ); gpAR->iButton[ BANDAGE_BUTTON ] = - QuickCreateButton( gpAR->iButtonImage[ BANDAGE_BUTTON ] , (INT16)(gpAR->sCenterStartX+11), (INT16)(245+gpAR->bVerticalOffset), BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGH, + QuickCreateButton( gpAR->iButtonImage[ BANDAGE_BUTTON ] , (INT16)(gpAR->sCenterStartX+11), (INT16)(iScreenHeightOffset + 245+gpAR->bVerticalOffset), BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, BandageButtonCallback ); gpAR->iButton[ DONEWIN_BUTTON ] = - QuickCreateButton( gpAR->iButtonImage[ DONEWIN_BUTTON ], (INT16)(gpAR->sCenterStartX+51), (INT16)(245+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, + QuickCreateButton( gpAR->iButtonImage[ DONEWIN_BUTTON ], (INT16)(gpAR->sCenterStartX+51), (INT16)(iScreenHeightOffset + 245+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, DoneButtonCallback ); SpecifyGeneralButtonTextAttributes( gpAR->iButton[ DONEWIN_BUTTON ], gpStrategicString[STR_AR_DONE_BUTTON], BLOCKFONT2, 169, FONT_NEARBLACK ); gpAR->iButton[ DONELOSE_BUTTON ] = - QuickCreateButton( gpAR->iButtonImage[ DONELOSE_BUTTON ], (INT16)(gpAR->sCenterStartX+25), (INT16)(245+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, + QuickCreateButton( gpAR->iButtonImage[ DONELOSE_BUTTON ], (INT16)(gpAR->sCenterStartX+25), (INT16)(iScreenHeightOffset + 245+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, DoneButtonCallback ); SpecifyGeneralButtonTextAttributes( gpAR->iButton[ DONELOSE_BUTTON ], gpStrategicString[STR_AR_DONE_BUTTON], BLOCKFONT2, 169, FONT_NEARBLACK ); gpAR->iButton[ YES_BUTTON ] = - QuickCreateButton( gpAR->iButtonImage[ YES_BUTTON ], (INT16)(gpAR->sCenterStartX+21), (INT16)(257+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, + QuickCreateButton( gpAR->iButtonImage[ YES_BUTTON ], (INT16)(gpAR->sCenterStartX+21), (INT16)(iScreenHeightOffset + 257+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, AcceptSurrenderCallback ); gpAR->iButton[ NO_BUTTON ] = - QuickCreateButton( gpAR->iButtonImage[ NO_BUTTON ], (INT16)(gpAR->sCenterStartX+81), (INT16)(257+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, + QuickCreateButton( gpAR->iButtonImage[ NO_BUTTON ], (INT16)(gpAR->sCenterStartX+81), (INT16)(iScreenHeightOffset + 257+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, RejectSurrenderCallback ); HideButton( gpAR->iButton[ YES_BUTTON ] ); HideButton( gpAR->iButton[ NO_BUTTON ] ); @@ -2839,11 +2855,13 @@ void CalculateRowsAndColumns() } if( gpAR->ubMercCols + gpAR->ubEnemyCols == 9 ) - gpAR->sWidth = 640; + gpAR->sWidth = SCREEN_WIDTH; else gpAR->sWidth = 146 + 55 * (max( max( gpAR->ubMercCols, gpAR->ubCivCols ), 2 ) + max( gpAR->ubEnemyCols, 2 )); - gpAR->sCenterStartX = 323 - gpAR->sWidth/2 + max( max( gpAR->ubMercCols, 2), max( gpAR->ubCivCols, 2 ) ) *55; + // WANNE 2 + //gpAR->sCenterStartX = 323 - gpAR->sWidth/2 + max( max( gpAR->ubMercCols, 2), max( gpAR->ubCivCols, 2 ) ) *55; + gpAR->sCenterStartX = iScreenWidthOffset + (323 - gpAR->sWidth/2 + max( max( gpAR->ubMercCols, 2), max( gpAR->ubCivCols, 2 ) ) *55); //Anywhere from 48*3 to 48*10 gpAR->sHeight = 48 * max( 3, max( gpAR->ubMercRows + gpAR->ubCivRows, gpAR->ubEnemyRows ) ); diff --git a/Strategic/Game Clock.h b/Strategic/Game Clock.h index 5b9fe554..18069183 100644 --- a/Strategic/Game Clock.h +++ b/Strategic/Game Clock.h @@ -1,3 +1,4 @@ +// WANNE 2 #ifndef __WORLD_CLOCK #define __WORLD_CLOCK @@ -5,14 +6,16 @@ // where the time string itself is rendered -#define CLOCK_X 554 -#define CLOCK_Y 459 +// WANNE 2 +#define CLOCK_X (SCREEN_WIDTH - 86) //554 +#define CLOCK_Y (SCREEN_HEIGHT - 21) //459 +// WANNE 2 // the mouse region around the clock (bigger) -#define CLOCK_REGION_START_X 552 -#define CLOCK_REGION_START_Y 456 -#define CLOCK_REGION_WIDTH ( 620 - CLOCK_REGION_START_X ) -#define CLOCK_REGION_HEIGHT ( 468 - CLOCK_REGION_START_Y ) +#define CLOCK_REGION_START_X (SCREEN_WIDTH - 88) //552 +#define CLOCK_REGION_START_Y (SCREEN_HEIGHT - 24) //456 +#define CLOCK_REGION_WIDTH ((SCREEN_WIDTH - 20) - CLOCK_REGION_START_X) // ( 620 - CLOCK_REGION_START_X ) +#define CLOCK_REGION_HEIGHT ((SCREEN_HEIGHT - 12) - CLOCK_REGION_START_Y) //( 468 - CLOCK_REGION_START_Y ) #define NUM_SEC_IN_DAY 86400 #define NUM_SEC_IN_HOUR 3600 diff --git a/Strategic/Map Screen Interface Border.cpp b/Strategic/Map Screen Interface Border.cpp index c69b9499..7b75f0b7 100644 --- a/Strategic/Map Screen Interface Border.cpp +++ b/Strategic/Map Screen Interface Border.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #else @@ -24,14 +25,13 @@ #include "strategicmap.h" #endif -#define MAP_BORDER_X 261 -#define MAP_BORDER_Y 0 - -#define MAP_BORDER_CORNER_X 584 -#define MAP_BORDER_CORNER_Y 279 + +//#define MAP_BORDER_CORNER_X 584 +//#define MAP_BORDER_CORNER_Y 279 + // extern to anchored button in winbart97 extern GUI_BUTTON *gpAnchoredButton; extern BOOLEAN gfAnchoredState; @@ -108,6 +108,9 @@ void LevelMarkerBtnCallback(MOUSE_REGION * pRegion, INT32 iReason ); void CommonBtnCallbackBtnDownChecks( void ); +// WANNE 2 +void DrawTextOnMapBorder( void ); + /* void BtnScrollNorthMapScreenCallback( GUI_BUTTON *btn,INT32 reason ); @@ -118,6 +121,31 @@ void BtnLowerLevelBtnCallback(GUI_BUTTON *btn,INT32 reason); void BtnRaiseLevelBtnCallback(GUI_BUTTON *btn,INT32 reason); */ +// WANNE 2 +void DrawTextOnMapBorder( void ) +{ + INT16 sX = 0, sY = 0; + CHAR16 sString[ 64 ]; + + // parse the string + swprintf( sString, zMarksMapScreenText[ 24 ] ); + + SetFontDestBuffer( guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); + + //FindFontCenterCoordinates( MAP_INV_X_OFFSET + MAP_INVENTORY_POOL_SLOT_START_X, MAP_INVENTORY_POOL_SLOT_START_Y - 20, 630 - MAP_INVENTORY_POOL_SLOT_START_X, GetFontHeight( FONT14ARIAL ), sString, FONT14ARIAL, &sX, &sY ); + + FindFontCenterCoordinates( 271, 18, SCREEN_WIDTH - 271, GetFontHeight( FONT14ARIAL ), sString, FONT14ARIAL, &sX, &sY ); + + SetFont( FONT14ARIAL ); + SetFontForeground( FONT_WHITE ); + SetFontBackground( FONT_BLACK ); + + mprintf( sX, sY, sString ); + + SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); + +} + BOOLEAN LoadMapBorderGraphics( void ) { @@ -133,11 +161,11 @@ BOOLEAN LoadMapBorderGraphics( void ) } else if (iResolution == 1) { - FilenameForBPP( "INTERFACE\\MBS_540x360.sti", VObjectDesc.ImageFile ); + FilenameForBPP( "INTERFACE\\MBS_800x600.sti", VObjectDesc.ImageFile ); } else if (iResolution == 2) { - FilenameForBPP( "INTERFACE\\MBS_764x360.sti", VObjectDesc.ImageFile ); + FilenameForBPP( "INTERFACE\\MBS_1024x768.sti", VObjectDesc.ImageFile ); } CHECKF( AddVideoObject( &VObjectDesc, &guiMapBorder ) ); @@ -189,7 +217,13 @@ void RenderMapBorder( void ) // get and blt border GetVideoObject(&hHandle, guiMapBorder ); - BltVideoObject( guiSAVEBUFFER , hHandle, 0,MAP_BORDER_X, MAP_BORDER_Y, VO_BLT_SRCTRANSPARENCY,NULL ); + BltVideoObject( guiSAVEBUFFER , hHandle, 0, MAP_BORDER_X, MAP_BORDER_Y, VO_BLT_SRCTRANSPARENCY,NULL ); + + // WANNE 2 + if (iResolution == 1 || iResolution == 2) + { + DrawTextOnMapBorder(); + } // WANNE Invalidate!! RestoreExternBackgroundRect( MAP_BORDER_X, MAP_BORDER_Y, SCREEN_WIDTH - MAP_BORDER_X, SCREEN_HEIGHT ); @@ -255,9 +289,15 @@ void RenderMapBorderEtaPopUp( void ) // get and blt ETA box GetVideoObject(&hHandle, guiMapBorderEtaPopUp ); - BltVideoObject( FRAME_BUFFER , hHandle, 0, MAP_BORDER_X + 215, 291, VO_BLT_SRCTRANSPARENCY,NULL ); + + // WANNE 2 + /*BltVideoObject( FRAME_BUFFER , hHandle, 0, MAP_BORDER_X + 215, 291, VO_BLT_SRCTRANSPARENCY,NULL ); - InvalidateRegion( MAP_BORDER_X + 215, 291, MAP_BORDER_X + 215 + 100 , 310); + InvalidateRegion( MAP_BORDER_X + 215, 291, MAP_BORDER_X + 215 + 100 , 310);*/ + + BltVideoObject( FRAME_BUFFER , hHandle, 0, MAP_BORDER_X + MAP_BORDER_X_OFFSET + 215, MAP_BORDER_Y_OFFSET + 291, VO_BLT_SRCTRANSPARENCY,NULL ); + + InvalidateRegion( MAP_BORDER_X + MAP_BORDER_X_OFFSET + 215, MAP_BORDER_Y_OFFSET + 291, MAP_BORDER_X + MAP_BORDER_X_OFFSET + 215 + 100 , MAP_BORDER_Y_OFFSET + 310); return; } @@ -299,40 +339,41 @@ BOOLEAN CreateButtonsForMapBorder( void ) */ + // WANNE 2 // towns giMapBorderButtonsImage[ MAP_BORDER_TOWN_BTN ] = LoadButtonImage( "INTERFACE\\map_border_buttons.sti" ,-1,5,-1,14,-1 ); - giMapBorderButtons[ MAP_BORDER_TOWN_BTN ] = QuickCreateButton( giMapBorderButtonsImage[ MAP_BORDER_TOWN_BTN ], 299, 323, + giMapBorderButtons[ MAP_BORDER_TOWN_BTN ] = QuickCreateButton( giMapBorderButtonsImage[ MAP_BORDER_TOWN_BTN ], MAP_BORDER_X + ((SCREEN_WIDTH - MAP_BORDER_X) / 2 - 152), (SCREEN_HEIGHT - 157), BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGH, (GUI_CALLBACK)MSYS_NO_CALLBACK, (GUI_CALLBACK)BtnTownCallback); // mines giMapBorderButtonsImage[ MAP_BORDER_MINE_BTN ] = LoadButtonImage( "INTERFACE\\map_border_buttons.sti" ,-1,4,-1,13,-1 ); - giMapBorderButtons[ MAP_BORDER_MINE_BTN ] = QuickCreateButton( giMapBorderButtonsImage[ MAP_BORDER_MINE_BTN ], 342, 323, + giMapBorderButtons[ MAP_BORDER_MINE_BTN ] = QuickCreateButton( giMapBorderButtonsImage[ MAP_BORDER_MINE_BTN ], MAP_BORDER_X + ((SCREEN_WIDTH - MAP_BORDER_X) / 2 - 109), (SCREEN_HEIGHT - 157), BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGH, (GUI_CALLBACK)MSYS_NO_CALLBACK, (GUI_CALLBACK)BtnMineCallback); // people giMapBorderButtonsImage[ MAP_BORDER_TEAMS_BTN ] = LoadButtonImage( "INTERFACE\\map_border_buttons.sti" ,-1,3,-1,12,-1 ); - giMapBorderButtons[ MAP_BORDER_TEAMS_BTN ] = QuickCreateButton( giMapBorderButtonsImage[ MAP_BORDER_TEAMS_BTN ], 385, 323, + giMapBorderButtons[ MAP_BORDER_TEAMS_BTN ] = QuickCreateButton( giMapBorderButtonsImage[ MAP_BORDER_TEAMS_BTN ], MAP_BORDER_X + ((SCREEN_WIDTH - MAP_BORDER_X) / 2 - 66), (SCREEN_HEIGHT - 157), BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGH, (GUI_CALLBACK)MSYS_NO_CALLBACK, (GUI_CALLBACK)BtnTeamCallback); // militia giMapBorderButtonsImage[ MAP_BORDER_MILITIA_BTN ] = LoadButtonImage( "INTERFACE\\map_border_buttons.sti" ,-1,8,-1,17,-1 ); - giMapBorderButtons[ MAP_BORDER_MILITIA_BTN ] = QuickCreateButton( giMapBorderButtonsImage[ MAP_BORDER_MILITIA_BTN ], 428, 323, + giMapBorderButtons[ MAP_BORDER_MILITIA_BTN ] = QuickCreateButton( giMapBorderButtonsImage[ MAP_BORDER_MILITIA_BTN ], MAP_BORDER_X + ((SCREEN_WIDTH - MAP_BORDER_X) / 2 - 23), (SCREEN_HEIGHT - 157), BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGH, (GUI_CALLBACK)MSYS_NO_CALLBACK, (GUI_CALLBACK)BtnMilitiaCallback); // airspace giMapBorderButtonsImage[ MAP_BORDER_AIRSPACE_BTN ] = LoadButtonImage( "INTERFACE\\map_border_buttons.sti" ,-1,2,-1,11,-1 ); - giMapBorderButtons[ MAP_BORDER_AIRSPACE_BTN ] = QuickCreateButton( giMapBorderButtonsImage[ MAP_BORDER_AIRSPACE_BTN ], 471, 323, + giMapBorderButtons[ MAP_BORDER_AIRSPACE_BTN ] = QuickCreateButton( giMapBorderButtonsImage[ MAP_BORDER_AIRSPACE_BTN ], MAP_BORDER_X + ((SCREEN_WIDTH - MAP_BORDER_X) / 2 + 19), (SCREEN_HEIGHT - 157), BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGH, (GUI_CALLBACK)MSYS_NO_CALLBACK, (GUI_CALLBACK)BtnAircraftCallback); // items giMapBorderButtonsImage[ MAP_BORDER_ITEM_BTN ] = LoadButtonImage( "INTERFACE\\map_border_buttons.sti" ,-1,1,-1,10,-1 ); - giMapBorderButtons[ MAP_BORDER_ITEM_BTN ] = QuickCreateButton( giMapBorderButtonsImage[ MAP_BORDER_ITEM_BTN ], 514, 323, + giMapBorderButtons[ MAP_BORDER_ITEM_BTN ] = QuickCreateButton( giMapBorderButtonsImage[ MAP_BORDER_ITEM_BTN ], MAP_BORDER_X + ((SCREEN_WIDTH - MAP_BORDER_X) / 2 + 62), (SCREEN_HEIGHT - 157), BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGH, (GUI_CALLBACK)MSYS_NO_CALLBACK, (GUI_CALLBACK)BtnItemCallback); @@ -1127,7 +1168,6 @@ BOOLEAN ScrollButtonsDisplayingHelpMessage( void ) void DisplayCurrentLevelMarker( void ) { // display the current level marker on the map border - HVOBJECT hHandle; /* @@ -1141,6 +1181,10 @@ void DisplayCurrentLevelMarker( void ) GetVideoObject(&hHandle, guiLEVELMARKER ); BltVideoObject( guiSAVEBUFFER , hHandle, 0, MAP_LEVEL_MARKER_X + 1, MAP_LEVEL_MARKER_Y + ( MAP_LEVEL_MARKER_DELTA * ( INT16 )iCurrentMapSectorZ ), VO_BLT_SRCTRANSPARENCY,NULL ); + // WANNE 2 + RestoreExternBackgroundRect(MAP_LEVEL_MARKER_X + 1, MAP_LEVEL_MARKER_Y + ( MAP_LEVEL_MARKER_DELTA * ( INT16 )iCurrentMapSectorZ ), 55, 9); + + return; } diff --git a/Strategic/Map Screen Interface Border.h b/Strategic/Map Screen Interface Border.h index 7bdc0af7..3b0a6683 100644 --- a/Strategic/Map Screen Interface Border.h +++ b/Strategic/Map Screen Interface Border.h @@ -3,8 +3,8 @@ #include "Types.h" -#define MAP_BORDER_START_X 261 -#define MAP_BORDER_START_Y 0 +//#define MAP_BORDER_START_X 261 +//#define MAP_BORDER_START_Y 0 @@ -41,10 +41,11 @@ enum{ */ -#define MAP_LEVEL_MARKER_X 565 -#define MAP_LEVEL_MARKER_Y 323 -#define MAP_LEVEL_MARKER_DELTA 8 -#define MAP_LEVEL_MARKER_WIDTH ( 620 - MAP_LEVEL_MARKER_X ) +// WANNE 2 +#define MAP_LEVEL_MARKER_X (MAP_BORDER_X + ((SCREEN_WIDTH - MAP_BORDER_X) / 2 + 114)) //MAP_BORDER_X + MAP_BORDER_X_OFFSET + 384 //(SCREEN_WIDTH - 75) //565 +#define MAP_LEVEL_MARKER_Y (SCREEN_HEIGHT - 157) //(SCREEN_HEIGHT - 157) //323 +#define MAP_LEVEL_MARKER_DELTA 8 +#define MAP_LEVEL_MARKER_WIDTH 55 //( (SCREEN_WIDTH - 20) - MAP_LEVEL_MARKER_X ) extern BOOLEAN fShowTownFlag; diff --git a/Strategic/Map Screen Interface Bottom.cpp b/Strategic/Map Screen Interface Bottom.cpp index db6129d8..39b641e0 100644 --- a/Strategic/Map Screen Interface Bottom.cpp +++ b/Strategic/Map Screen Interface Bottom.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #else @@ -38,30 +39,31 @@ #endif -#define MAP_BOTTOM_X 0 -#define MAP_BOTTOM_Y 359 +// WANNE 2 +#define MAP_BOTTOM_X 0 +#define MAP_BOTTOM_Y (SCREEN_HEIGHT - 121) //359 -#define MESSAGE_SCROLL_AREA_START_X 330 -#define MESSAGE_SCROLL_AREA_END_X 344 -#define MESSAGE_SCROLL_AREA_WIDTH ( MESSAGE_SCROLL_AREA_END_X - MESSAGE_SCROLL_AREA_START_X + 1 ) +#define MESSAGE_SCROLL_AREA_START_X 330 +#define MESSAGE_SCROLL_AREA_END_X 344 +#define MESSAGE_SCROLL_AREA_WIDTH ( MESSAGE_SCROLL_AREA_END_X - MESSAGE_SCROLL_AREA_START_X + 1 ) -#define MESSAGE_SCROLL_AREA_START_Y 390 -#define MESSAGE_SCROLL_AREA_END_Y 448 -#define MESSAGE_SCROLL_AREA_HEIGHT ( MESSAGE_SCROLL_AREA_END_Y - MESSAGE_SCROLL_AREA_START_Y + 1 ) +#define MESSAGE_SCROLL_AREA_START_Y (SCREEN_HEIGHT - 90) //390 +#define MESSAGE_SCROLL_AREA_END_Y (SCREEN_HEIGHT - 32) //448 +#define MESSAGE_SCROLL_AREA_HEIGHT ( MESSAGE_SCROLL_AREA_END_Y - MESSAGE_SCROLL_AREA_START_Y + 1 ) -#define SLIDER_HEIGHT 11 -#define SLIDER_WIDTH 11 +#define SLIDER_HEIGHT 11 +#define SLIDER_WIDTH 11 -#define SLIDER_BAR_RANGE ( MESSAGE_SCROLL_AREA_HEIGHT - SLIDER_HEIGHT ) +#define SLIDER_BAR_RANGE ( MESSAGE_SCROLL_AREA_HEIGHT - SLIDER_HEIGHT ) -#define MESSAGE_BTN_SCROLL_TIME 100 +#define MESSAGE_BTN_SCROLL_TIME 100 // delay for paused flash -#define PAUSE_GAME_TIMER 500 +#define PAUSE_GAME_TIMER 500 -#define MAP_BOTTOM_FONT_COLOR ( 32 * 4 - 9 ) +#define MAP_BOTTOM_FONT_COLOR ( 32 * 4 - 9 ) /* // delay to start auto message scroll @@ -148,7 +150,6 @@ extern BOOLEAN fShowDescriptionFlag; extern MOUSE_REGION gMPanelRegion; - // PROTOTYPES @@ -205,15 +206,15 @@ void HandleLoadOfMapBottomGraphics( void ) if (iResolution == 0) { - FilenameForBPP( "INTERFACE\\map_screen_bottom.sti", VObjectDesc.ImageFile ); + FilenameForBPP( "INTERFACE\\map_screen_bottom.sti", VObjectDesc.ImageFile ); } else if (iResolution == 1) { - FilenameForBPP( "INTERFACE\\map_screen_bottom_800x241.sti", VObjectDesc.ImageFile ); + FilenameForBPP( "INTERFACE\\map_screen_bottom_800x600.sti", VObjectDesc.ImageFile ); } else if (iResolution == 2) { - FilenameForBPP( "INTERFACE\\map_screen_bottom_1024x409.sti", VObjectDesc.ImageFile ); + FilenameForBPP( "INTERFACE\\map_screen_bottom_1024x768.sti", VObjectDesc.ImageFile ); } if( !AddVideoObject( &VObjectDesc, &guiMAPBOTTOMPANEL ) ) @@ -267,7 +268,11 @@ void RenderMapScreenInterfaceBottom( void ) HVOBJECT hHandle; CHAR8 bFilename[ 32 ]; - + // WANNE 2 + fDisplayOverheadMap = FALSE; + + + // WANNE 2 // render whole panel if( fMapScreenBottomDirty == TRUE ) { @@ -293,7 +298,7 @@ void RenderMapScreenInterfaceBottom( void ) // dirty buttons MarkButtonsDirty( ); - // WANNE + // WANNE 2 // invalidate region RestoreExternBackgroundRect( MAP_BOTTOM_X, MAP_BOTTOM_Y, SCREEN_WIDTH, SCREEN_HEIGHT - MAP_BOTTOM_Y ); @@ -335,20 +340,20 @@ BOOLEAN CreateButtonsForMapScreenInterfaceBottom( void ) { // laptop guiMapBottomExitButtonsImage[ MAP_EXIT_TO_LAPTOP ]= LoadButtonImage( "INTERFACE\\map_border_buttons.sti" ,-1,6,-1,15,-1 ); - guiMapBottomExitButtons[ MAP_EXIT_TO_LAPTOP ] = QuickCreateButton( guiMapBottomExitButtonsImage[ MAP_EXIT_TO_LAPTOP ], 456, 410, + guiMapBottomExitButtons[ MAP_EXIT_TO_LAPTOP ] = QuickCreateButton( guiMapBottomExitButtonsImage[ MAP_EXIT_TO_LAPTOP ], (SCREEN_WIDTH - 184), (SCREEN_HEIGHT - 70), BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnLaptopCallback); // tactical guiMapBottomExitButtonsImage[ MAP_EXIT_TO_TACTICAL ]= LoadButtonImage( "INTERFACE\\map_border_buttons.sti" ,-1,7,-1,16,-1 ); - guiMapBottomExitButtons[ MAP_EXIT_TO_TACTICAL ] = QuickCreateButton( guiMapBottomExitButtonsImage[ MAP_EXIT_TO_TACTICAL ], 496, 410, + guiMapBottomExitButtons[ MAP_EXIT_TO_TACTICAL ] = QuickCreateButton( guiMapBottomExitButtonsImage[ MAP_EXIT_TO_TACTICAL ], (SCREEN_WIDTH - 144), (SCREEN_HEIGHT - 70), BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnTacticalCallback); // options guiMapBottomExitButtonsImage[ MAP_EXIT_TO_OPTIONS ]= LoadButtonImage( "INTERFACE\\map_border_buttons.sti" ,-1,18,-1,19,-1 ); - guiMapBottomExitButtons[ MAP_EXIT_TO_OPTIONS ] = QuickCreateButton( guiMapBottomExitButtonsImage[ MAP_EXIT_TO_OPTIONS ], 458, 372, + guiMapBottomExitButtons[ MAP_EXIT_TO_OPTIONS ] = QuickCreateButton( guiMapBottomExitButtonsImage[ MAP_EXIT_TO_OPTIONS ], (SCREEN_WIDTH - 182), (SCREEN_HEIGHT - 108), BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnOptionsFromMapScreenCallback); @@ -364,12 +369,12 @@ BOOLEAN CreateButtonsForMapScreenInterfaceBottom( void ) // time compression buttons guiMapBottomTimeButtonsImage[ MAP_TIME_COMPRESS_MORE ]= LoadButtonImage( "INTERFACE\\map_screen_bottom_arrows.sti" ,10,1,-1,3,-1 ); - guiMapBottomTimeButtons[ MAP_TIME_COMPRESS_MORE ] = QuickCreateButton( guiMapBottomTimeButtonsImage[ MAP_TIME_COMPRESS_MORE ], 528, 456, + guiMapBottomTimeButtons[ MAP_TIME_COMPRESS_MORE ] = QuickCreateButton( guiMapBottomTimeButtonsImage[ MAP_TIME_COMPRESS_MORE ], (SCREEN_WIDTH - 112), (SCREEN_HEIGHT - 24), BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 2 , (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnTimeCompressMoreMapScreenCallback); guiMapBottomTimeButtonsImage[ MAP_TIME_COMPRESS_LESS ]= LoadButtonImage( "INTERFACE\\map_screen_bottom_arrows.sti" ,9,0,-1,2,-1 ); - guiMapBottomTimeButtons[ MAP_TIME_COMPRESS_LESS ] = QuickCreateButton( guiMapBottomTimeButtonsImage[ MAP_TIME_COMPRESS_LESS ], 466, 456, + guiMapBottomTimeButtons[ MAP_TIME_COMPRESS_LESS ] = QuickCreateButton( guiMapBottomTimeButtonsImage[ MAP_TIME_COMPRESS_LESS ], (SCREEN_WIDTH - 174), (SCREEN_HEIGHT - 24), BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 2, (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnTimeCompressLessMapScreenCallback); @@ -383,12 +388,12 @@ BOOLEAN CreateButtonsForMapScreenInterfaceBottom( void ) // scroll buttons guiMapMessageScrollButtonsImage[ MAP_SCROLL_MESSAGE_UP ]= LoadButtonImage( "INTERFACE\\map_screen_bottom_arrows.sti" ,11,4,-1,6,-1 ); - guiMapMessageScrollButtons[ MAP_SCROLL_MESSAGE_UP ] = QuickCreateButton( guiMapMessageScrollButtonsImage[ MAP_SCROLL_MESSAGE_UP ], 331, 371, + guiMapMessageScrollButtons[ MAP_SCROLL_MESSAGE_UP ] = QuickCreateButton( guiMapMessageScrollButtonsImage[ MAP_SCROLL_MESSAGE_UP ], 331, (SCREEN_HEIGHT - 109), BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnMessageUpMapScreenCallback); guiMapMessageScrollButtonsImage[ MAP_SCROLL_MESSAGE_DOWN ]= LoadButtonImage( "INTERFACE\\map_screen_bottom_arrows.sti" ,12,5,-1,7,-1 ); - guiMapMessageScrollButtons[ MAP_SCROLL_MESSAGE_DOWN ] = QuickCreateButton( guiMapMessageScrollButtonsImage[ MAP_SCROLL_MESSAGE_DOWN ], 331, 452, + guiMapMessageScrollButtons[ MAP_SCROLL_MESSAGE_DOWN ] = QuickCreateButton( guiMapMessageScrollButtonsImage[ MAP_SCROLL_MESSAGE_DOWN ], 331, (SCREEN_HEIGHT - 28), BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnMessageDownMapScreenCallback); @@ -574,7 +579,9 @@ void DrawNameOfLoadedSector( void ) GetSectorIDString( sSelMapX, sSelMapY, ( INT8 )( iCurrentMapSectorZ ),sString, TRUE ); ReduceStringLength( sString, 80, COMPFONT ); - VarFindFontCenterCoordinates( 548, 426, 80, 16, COMPFONT, &sFontX, &sFontY, sString ); + // WANNE 2 + //VarFindFontCenterCoordinates( 548, 426, 80, 16, COMPFONT, &sFontX, &sFontY, sString ); + VarFindFontCenterCoordinates( (SCREEN_WIDTH - 92), (SCREEN_HEIGHT - 55), 80, 16, COMPFONT, &sFontX, &sFontY, sString ); mprintf( sFontX, sFontY, L"%s", sString ); } @@ -917,7 +924,10 @@ void DisplayCompressMode( void ) } } - RestoreExternBackgroundRect( 489, 456, 522 - 489, 467 - 454 ); + //RestoreExternBackgroundRect( 489, 456, 522 - 489, 467 - 454 ); + // WANNE 2 + RestoreExternBackgroundRect( (SCREEN_WIDTH - 151), (SCREEN_HEIGHT - 24), 63, 13 ); + SetFontDestBuffer( FRAME_BUFFER, 0,0,SCREEN_WIDTH,SCREEN_HEIGHT, FALSE ); SetFont( COMPFONT ); @@ -942,7 +952,10 @@ void DisplayCompressMode( void ) SetFontForeground( usColor ); SetFontBackground( FONT_BLACK ); - FindFontCenterCoordinates( 489, 456, 522 - 489, 467 - 454, sString, COMPFONT, &sX, &sY ); + + // WANNE 2 + //FindFontCenterCoordinates( 489, 456, 522 - 489, 467 - 454, sString, COMPFONT, &sX, &sY ); + FindFontCenterCoordinates( (SCREEN_WIDTH - 151), (SCREEN_HEIGHT - 24), 33, 13, sString, COMPFONT, &sX, &sY ); mprintf( sX, sY, sString ); @@ -952,7 +965,11 @@ void DisplayCompressMode( void ) void CreateCompressModePause( void ) { - MSYS_DefineRegion( &gMapPauseRegion, 487, 456, 522, 467, MSYS_PRIORITY_HIGH, + /*MSYS_DefineRegion( &gMapPauseRegion, 487, 456, 522, 467, MSYS_PRIORITY_HIGH, + MSYS_NO_CURSOR, MSYS_NO_CALLBACK, CompressModeClickCallback );*/ + + // WANNE 2 + MSYS_DefineRegion( &gMapPauseRegion, (SCREEN_WIDTH - 153), (SCREEN_HEIGHT - 24), (SCREEN_WIDTH - 118), (SCREEN_HEIGHT - 13), MSYS_PRIORITY_HIGH, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, CompressModeClickCallback ); SetRegionFastHelpText( &gMapPauseRegion, pMapScreenBottomFastHelp[ 7 ] ); @@ -1367,17 +1384,21 @@ void DisplayCurrentBalanceTitleForMapBottom( void ) swprintf( sString, L"%s", pMapScreenBottomText[ 0 ] ); + // WANNE 2 // center it - VarFindFontCenterCoordinates( 359, 387 - 14, 437 - 359, 10, COMPFONT, &sFontX, &sFontY, sString ); + VarFindFontCenterCoordinates( 359, (SCREEN_HEIGHT - 107), 78, 10, COMPFONT, &sFontX, &sFontY, sString ); + //VarFindFontCenterCoordinates( 359, 387 - 14, 437 - 359, 10, COMPFONT, &sFontX, &sFontY, sString ); // print it mprintf( sFontX, sFontY, L"%s", sString ); swprintf( sString, L"%s", zMarksMapScreenText[ 2 ] ); + // WANNE 2 // center it - VarFindFontCenterCoordinates( 359, 433 - 14, 437 - 359, 10, COMPFONT, &sFontX, &sFontY, sString ); - + //VarFindFontCenterCoordinates( 359, 433 - 14, 437 - 359, 10, COMPFONT, &sFontX, &sFontY, sString ); + VarFindFontCenterCoordinates( 359, (SCREEN_HEIGHT - 61), 78, 10, COMPFONT, &sFontX, &sFontY, sString ); + // print it mprintf( sFontX, sFontY, L"%s", sString ); @@ -1407,8 +1428,9 @@ void DisplayCurrentBalanceForMapBottom( void ) InsertCommasForDollarFigure( sString ); InsertDollarSignInToString( sString ); + // WANNE 2 // center it - VarFindFontCenterCoordinates( 359, 387 + 2, 437 - 359, 10, COMPFONT, &sFontX, &sFontY, sString ); + VarFindFontCenterCoordinates( 359, (SCREEN_HEIGHT - 91), 78, 10, COMPFONT, &sFontX, &sFontY, sString ); // print it mprintf( sFontX, sFontY, L"%s", sString ); @@ -1436,16 +1458,30 @@ void CreateDestroyMouseRegionMasksForTimeCompressionButtons( void ) // check if disabled and not created, create if( ( fDisabled ) && ( fCreated == FALSE ) ) { + // mask over compress more button - MSYS_DefineRegion( &gTimeCompressionMask[ 0 ], 528, 456, 528 + 13, 456 + 14, MSYS_PRIORITY_HIGHEST - 1, + //MSYS_DefineRegion( &gTimeCompressionMask[ 0 ], 528, 456, 528 + 13, 456 + 14, MSYS_PRIORITY_HIGHEST - 1, + // MSYS_NO_CURSOR, MSYS_NO_CALLBACK, CompressMaskClickCallback ); + + //// mask over compress less button + //MSYS_DefineRegion( &gTimeCompressionMask[ 1 ], 466, 456, 466 + 13, 456 + 14, MSYS_PRIORITY_HIGHEST - 1, + // MSYS_NO_CURSOR, MSYS_NO_CALLBACK, CompressMaskClickCallback ); + + //// mask over pause game button + //MSYS_DefineRegion( &gTimeCompressionMask[ 2 ], 487, 456, 522, 467, MSYS_PRIORITY_HIGHEST - 1, + // MSYS_NO_CURSOR, MSYS_NO_CALLBACK, CompressMaskClickCallback ); + + // WANNE 2 + // mask over compress more button + MSYS_DefineRegion( &gTimeCompressionMask[ 0 ], (SCREEN_WIDTH - 112), (SCREEN_HEIGHT - 24), (SCREEN_WIDTH - 112) + 13, (SCREEN_HEIGHT - 24) + 14, MSYS_PRIORITY_HIGHEST - 1, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, CompressMaskClickCallback ); // mask over compress less button - MSYS_DefineRegion( &gTimeCompressionMask[ 1 ], 466, 456, 466 + 13, 456 + 14, MSYS_PRIORITY_HIGHEST - 1, + MSYS_DefineRegion( &gTimeCompressionMask[ 1 ], (SCREEN_WIDTH - 174), (SCREEN_HEIGHT - 24), (SCREEN_WIDTH - 174) + 13, (SCREEN_HEIGHT - 24) + 14, MSYS_PRIORITY_HIGHEST - 1, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, CompressMaskClickCallback ); // mask over pause game button - MSYS_DefineRegion( &gTimeCompressionMask[ 2 ], 487, 456, 522, 467, MSYS_PRIORITY_HIGHEST - 1, + MSYS_DefineRegion( &gTimeCompressionMask[ 2 ], (SCREEN_WIDTH - 153), (SCREEN_HEIGHT - 24), (SCREEN_WIDTH - 118), (SCREEN_HEIGHT - 13), MSYS_PRIORITY_HIGHEST - 1, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, CompressMaskClickCallback ); fCreated = TRUE; @@ -1506,7 +1542,8 @@ void DisplayProjectedDailyMineIncome( void ) InsertDollarSignInToString( sString ); // center it - VarFindFontCenterCoordinates( 359, 433 + 2, 437 - 359, 10, COMPFONT, &sFontX, &sFontY, sString ); + // WANNE 2 + VarFindFontCenterCoordinates( 359, (SCREEN_HEIGHT - 45), 78, 10, COMPFONT, &sFontX, &sFontY, sString ); // print it mprintf( sFontX, sFontY, L"%s", sString ); @@ -1715,7 +1752,9 @@ void HandleExitsFromMapScreen( void ) if( gfExtraBuffer ) { //Then initiate the transition animation from the mapscreen to laptop... - BlitBufferToBuffer( FRAME_BUFFER, guiEXTRABUFFER, 0, 0, 640, 480 ); + + // WANNE 2 + BlitBufferToBuffer( FRAME_BUFFER, guiEXTRABUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); gfStartMapScreenToLaptopTransition = TRUE; } break; diff --git a/Strategic/Map Screen Interface Map Inventory.cpp b/Strategic/Map Screen Interface Map Inventory.cpp index d2062e96..1cf69f97 100644 --- a/Strategic/Map Screen Interface Map Inventory.cpp +++ b/Strategic/Map Screen Interface Map Inventory.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #include "GameSettings.h" @@ -32,26 +33,30 @@ extern BOOLEAN SaveWorldItemsToTempItemFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ, UINT32 uiNumberOfItems, WORLDITEM *pData ); +// WANNE 2 +#define MAP_INV_X_OFFSET (((SCREEN_WIDTH - 261) - 380) / 2) +//#define MAP_INV_Y_OFFSET (((SCREEN_HEIGHT - 121) - + // status bar colors #define DESC_STATUS_BAR FROMRGB( 201, 172, 133 ) #define DESC_STATUS_BAR_SHADOW FROMRGB( 140, 136, 119 ) // page display positions -#define MAP_INVENTORY_POOL_PAGE_X 506 -#define MAP_INVENTORY_POOL_PAGE_Y 336 -#define MAP_INVENTORY_POOL_PAGE_WIDTH 46 //552 - 494 -#define MAP_INVENTORY_POOL_PAGE_HEIGHT 345 - 332 +#define MAP_INVENTORY_POOL_PAGE_X (MAP_INV_X_OFFSET + 506) +#define MAP_INVENTORY_POOL_PAGE_Y (SCREEN_HEIGHT - 121 - 23) //336 +#define MAP_INVENTORY_POOL_PAGE_WIDTH 46 +#define MAP_INVENTORY_POOL_PAGE_HEIGHT 13 // the number of items -#define MAP_INVENTORY_POOL_NUMBER_X 436 -#define MAP_INVENTORY_POOL_NUMBER_WIDTH 474 - 434 +#define MAP_INVENTORY_POOL_NUMBER_X (MAP_INV_X_OFFSET + 436) +#define MAP_INVENTORY_POOL_NUMBER_WIDTH 40 // location -#define MAP_INVENTORY_POOL_LOC_X 326 -#define MAP_INVENTORY_POOL_LOC_WIDTH 366 - 326 +#define MAP_INVENTORY_POOL_LOC_X MAP_INV_X_OFFSET + 326 +#define MAP_INVENTORY_POOL_LOC_WIDTH 40 // delay for flash of item -#define DELAY_FOR_HIGHLIGHT_ITEM_FLASH 200 +#define DELAY_FOR_HIGHLIGHT_ITEM_FLASH 200 // inventory slot font #define MAP_IVEN_FONT SMALLCOMPFONT @@ -73,14 +78,22 @@ extern BOOLEAN SaveWorldItemsToTempItemFile( INT16 sMapX, INT16 sMapY, INT8 bMap #define ITEMDESC_ITEM_STATUS_INV_POOL_OFFSET_Y 22 // inventory pool slot positions and sizes -#define MAP_INVENTORY_POOL_SLOT_START_X 271 -#define MAP_INVENTORY_POOL_SLOT_START_Y 36 -#define MAP_INV_SLOT_COLS 9 +//#define MAP_INVENTORY_POOL_SLOT_START_X 271 +//#define MAP_INVENTORY_POOL_SLOT_START_Y 36 #define MAP_INVEN_SLOT_WIDTH 65 #define MAP_INVEN_SPACE_BTWN_SLOTS 72 #define MAP_INVEN_SLOT_HEIGHT 32 #define MAP_INVEN_SLOT_IMAGE_HEIGHT 24 +// WANNE 2 +// Number of inventory slots in 1024x768 +#define MAP_INVENTORY_POOL_MAX_SLOTS 170 + +INT32 MAP_INV_SLOT_COLS; // Number of vertical slots +INT32 MAP_INVENTORY_POOL_SLOT_COUNT; + +INT32 MAP_INVENTORY_POOL_SLOT_START_X; +INT32 MAP_INVENTORY_POOL_SLOT_START_Y; // the current highlighted item INT32 iCurrentlyHighLightedItem = -1; @@ -109,9 +122,14 @@ UINT32 uiNumberOfUnSeenItems = 0; // the inventory slots -MOUSE_REGION MapInventoryPoolSlots[ MAP_INVENTORY_POOL_SLOT_COUNT ]; +// WANNE 2 +//MOUSE_REGION MapInventoryPoolSlots[ MAP_INVENTORY_POOL_SLOT_COUNT ]; +MOUSE_REGION MapInventoryPoolSlots[ MAP_INVENTORY_POOL_MAX_SLOTS ]; + MOUSE_REGION MapInventoryPoolMask; -BOOLEAN fMapInventoryItemCompatable[ MAP_INVENTORY_POOL_SLOT_COUNT ]; +//BOOLEAN fMapInventoryItemCompatable[ MAP_INVENTORY_POOL_SLOT_COUNT ]; +BOOLEAN fMapInventoryItemCompatable[ MAP_INVENTORY_POOL_MAX_SLOTS ]; + BOOLEAN fChangedInventorySlots = FALSE; // the unseen items list...have to save this @@ -201,7 +219,32 @@ BOOLEAN LoadInventoryPoolGraphic( void ) // load the file VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; - sprintf( VObjectDesc.ImageFile, "INTERFACE\\sector_inventory.sti" ); + + // WANNE 2 + if (iResolution == 0) + { + MAP_INV_SLOT_COLS = 8; + MAP_INVENTORY_POOL_SLOT_COUNT = 40; + MAP_INVENTORY_POOL_SLOT_START_X = 269; + MAP_INVENTORY_POOL_SLOT_START_Y = 51; + sprintf( VObjectDesc.ImageFile, "INTERFACE\\sector_inventory.sti" ); + } + else if (iResolution == 1) + { + MAP_INV_SLOT_COLS = 11; + MAP_INVENTORY_POOL_SLOT_COUNT = 77; + MAP_INVENTORY_POOL_SLOT_START_X = 278; + MAP_INVENTORY_POOL_SLOT_START_Y = 62; + sprintf( VObjectDesc.ImageFile, "INTERFACE\\sector_inventory_800x600.sti" ); + } + else if (iResolution == 2) + { + MAP_INV_SLOT_COLS = 17; + MAP_INVENTORY_POOL_SLOT_COUNT = MAP_INVENTORY_POOL_MAX_SLOTS; + MAP_INVENTORY_POOL_SLOT_START_X = 282; + MAP_INVENTORY_POOL_SLOT_START_Y = 50; + sprintf( VObjectDesc.ImageFile, "INTERFACE\\sector_inventory_1024x768.sti" ); + } // add to V-object index CHECKF(AddVideoObject(&VObjectDesc, &guiMapInventoryPoolBackground)); @@ -260,6 +303,10 @@ void BlitInventoryPoolGraphic( void ) // which buttons will be active and which ones not HandleButtonStatesWhileMapInventoryActive( ); + // WANNE 2 + // Invalidate + RestoreExternBackgroundRect(MAP_BORDER_X, MAP_BORDER_Y, SCREEN_WIDTH - MAP_BORDER_X, SCREEN_HEIGHT - 121); + return; } @@ -674,8 +721,13 @@ void CreateMapInventoryPoolSlots( void ) INT16 sULX = 0, sULY = 0; INT16 sBRX = 0, sBRY = 0; + // WANNE 2 + //MSYS_DefineRegion( &MapInventoryPoolMask, + // MAP_INVENTORY_POOL_SLOT_START_X, 0, 640, 360, + // MSYS_PRIORITY_HIGH, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MapInvenPoolScreenMaskCallback); + MSYS_DefineRegion( &MapInventoryPoolMask, - MAP_INVENTORY_POOL_SLOT_START_X, 0, 640, 360, + MAP_INVENTORY_POOL_SLOT_START_X, 0, SCREEN_WIDTH - MAP_INVENTORY_POOL_SLOT_START_X, SCREEN_HEIGHT - 120, MSYS_PRIORITY_HIGH, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MapInvenPoolScreenMaskCallback); for( iCounter = 0; iCounter < MAP_INVENTORY_POOL_SLOT_COUNT; iCounter++ ) @@ -938,13 +990,13 @@ void MapInvenPoolSlots(MOUSE_REGION * pRegion, INT32 iReason ) void CreateMapInventoryButtons( void ) { guiMapInvenButtonImage[ 0 ]= LoadButtonImage( "INTERFACE\\map_screen_bottom_arrows.sti" , 10, 1, -1, 3, -1 ); - guiMapInvenButton[ 0 ] = QuickCreateButton( guiMapInvenButtonImage[ 0 ], 559 , 336, + guiMapInvenButton[ 0 ] = QuickCreateButton( guiMapInvenButtonImage[ 0 ], (MAP_INV_X_OFFSET + 559), (SCREEN_HEIGHT - 144), BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST, (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)MapInventoryPoolNextBtn ); guiMapInvenButtonImage[ 1 ]= LoadButtonImage( "INTERFACE\\map_screen_bottom_arrows.sti" ,9, 0, -1, 2, -1 ); - guiMapInvenButton[ 1 ] = QuickCreateButton( guiMapInvenButtonImage[ 1 ], 487, 336, + guiMapInvenButton[ 1 ] = QuickCreateButton( guiMapInvenButtonImage[ 1 ], (MAP_INV_X_OFFSET + 487), (SCREEN_HEIGHT - 144), BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST, (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)MapInventoryPoolPrevBtn ); @@ -1679,7 +1731,7 @@ void DisplayPagesForMapInventoryPool( void ) mprintf( sX, sY, sString ); - SetFontDestBuffer( FRAME_BUFFER, 0,0, 640, 480, FALSE ); + SetFontDestBuffer( FRAME_BUFFER, 0,0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); } @@ -1752,9 +1804,10 @@ void DrawNumberOfIventoryPoolItems( void ) void CreateMapInventoryPoolDoneButton( void ) { + // WANNE 2 // create done button guiMapInvenButtonImage[ 2 ]= LoadButtonImage( "INTERFACE\\done_button.sti" , -1, 0, -1, 1, -1 ); - guiMapInvenButton[ 2 ] = QuickCreateButton( guiMapInvenButtonImage[ 2 ], 587 , 333, + guiMapInvenButton[ 2 ] = QuickCreateButton( guiMapInvenButtonImage[ 2 ], MAP_INV_X_OFFSET + 587 , (SCREEN_HEIGHT - 147), BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST, (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)MapInventoryPoolDoneBtn ); @@ -1831,13 +1884,22 @@ void DrawTextOnMapInventoryBackground( void ) // set the buffer SetFontDestBuffer( guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); + ////Calculate the height of the string, as it needs to be vertically centered. + //usStringHeight = DisplayWrappedString( 268, 342, 53, 1, MAP_IVEN_FONT, FONT_BEIGE, pMapInventoryStrings[ 0 ], FONT_BLACK, FALSE, RIGHT_JUSTIFIED | DONT_DISPLAY_TEXT ); + //DisplayWrappedString( 268, (UINT16)(342 - (usStringHeight / 2) ), 53, 1, MAP_IVEN_FONT, FONT_BEIGE, pMapInventoryStrings[ 0 ], FONT_BLACK, FALSE, RIGHT_JUSTIFIED ); + + ////Calculate the height of the string, as it needs to be vertically centered. + //usStringHeight = DisplayWrappedString( 369, 342, 65, 1, MAP_IVEN_FONT, FONT_BEIGE, pMapInventoryStrings[ 1 ], FONT_BLACK, FALSE, RIGHT_JUSTIFIED | DONT_DISPLAY_TEXT ); + //DisplayWrappedString( 369, (UINT16)(342 - (usStringHeight / 2) ), 65, 1, MAP_IVEN_FONT, FONT_BEIGE, pMapInventoryStrings[ 1 ], FONT_BLACK, FALSE, RIGHT_JUSTIFIED ); + + // WANNE 2 //Calculate the height of the string, as it needs to be vertically centered. - usStringHeight = DisplayWrappedString( 268, 342, 53, 1, MAP_IVEN_FONT, FONT_BEIGE, pMapInventoryStrings[ 0 ], FONT_BLACK, FALSE, RIGHT_JUSTIFIED | DONT_DISPLAY_TEXT ); - DisplayWrappedString( 268, (UINT16)(342 - (usStringHeight / 2) ), 53, 1, MAP_IVEN_FONT, FONT_BEIGE, pMapInventoryStrings[ 0 ], FONT_BLACK, FALSE, RIGHT_JUSTIFIED ); + usStringHeight = DisplayWrappedString( MAP_INV_X_OFFSET + 268, (SCREEN_HEIGHT - 138), 53, 1, MAP_IVEN_FONT, FONT_BEIGE, pMapInventoryStrings[ 0 ], FONT_BLACK, FALSE, RIGHT_JUSTIFIED | DONT_DISPLAY_TEXT ); + DisplayWrappedString( MAP_INV_X_OFFSET + 268, (UINT16)((SCREEN_HEIGHT - 138) - (usStringHeight / 2) ), 53, 1, MAP_IVEN_FONT, FONT_BEIGE, pMapInventoryStrings[ 0 ], FONT_BLACK, FALSE, RIGHT_JUSTIFIED ); //Calculate the height of the string, as it needs to be vertically centered. - usStringHeight = DisplayWrappedString( 369, 342, 65, 1, MAP_IVEN_FONT, FONT_BEIGE, pMapInventoryStrings[ 1 ], FONT_BLACK, FALSE, RIGHT_JUSTIFIED | DONT_DISPLAY_TEXT ); - DisplayWrappedString( 369, (UINT16)(342 - (usStringHeight / 2) ), 65, 1, MAP_IVEN_FONT, FONT_BEIGE, pMapInventoryStrings[ 1 ], FONT_BLACK, FALSE, RIGHT_JUSTIFIED ); + usStringHeight = DisplayWrappedString( MAP_INV_X_OFFSET + 369, (SCREEN_HEIGHT - 138), 65, 1, MAP_IVEN_FONT, FONT_BEIGE, pMapInventoryStrings[ 1 ], FONT_BLACK, FALSE, RIGHT_JUSTIFIED | DONT_DISPLAY_TEXT ); + DisplayWrappedString( MAP_INV_X_OFFSET + 369, (UINT16)((SCREEN_HEIGHT - 138) - (usStringHeight / 2) ), 65, 1, MAP_IVEN_FONT, FONT_BEIGE, pMapInventoryStrings[ 1 ], FONT_BLACK, FALSE, RIGHT_JUSTIFIED ); DrawTextOnSectorInventory( ); @@ -1898,7 +1960,9 @@ void DrawTextOnSectorInventory( void ) SetFontDestBuffer( guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); - FindFontCenterCoordinates( MAP_INVENTORY_POOL_SLOT_START_X, MAP_INVENTORY_POOL_SLOT_START_Y - 20, 630 - MAP_INVENTORY_POOL_SLOT_START_X, GetFontHeight( FONT14ARIAL ), sString, FONT14ARIAL, &sX, &sY ); + //FindFontCenterCoordinates( MAP_INV_X_OFFSET + MAP_INVENTORY_POOL_SLOT_START_X, MAP_INVENTORY_POOL_SLOT_START_Y - 20, 630 - MAP_INVENTORY_POOL_SLOT_START_X, GetFontHeight( FONT14ARIAL ), sString, FONT14ARIAL, &sX, &sY ); + + FindFontCenterCoordinates( 271, 18, SCREEN_WIDTH - 271, GetFontHeight( FONT14ARIAL ), sString, FONT14ARIAL, &sX, &sY ); SetFont( FONT14ARIAL ); SetFontForeground( FONT_WHITE ); diff --git a/Strategic/Map Screen Interface Map Inventory.h b/Strategic/Map Screen Interface Map Inventory.h index c8cbdefd..6bdd3c30 100644 --- a/Strategic/Map Screen Interface Map Inventory.h +++ b/Strategic/Map Screen Interface Map Inventory.h @@ -1,3 +1,4 @@ +// WANNE 2 #ifndef _MAP_INTERFACE_MAP_INVEN_H #define _MAP_INTERFACE_MAP_INVEN_H @@ -8,7 +9,7 @@ #define MAX_DISTANCE_TO_PICKUP_ITEM 5 // number of inventory slots -#define MAP_INVENTORY_POOL_SLOT_COUNT 45 +//#define MAP_INVENTORY_POOL_SLOT_COUNT 84 //45 //45 // whether we are showing the inventory pool graphic extern BOOLEAN fShowMapInventoryPool; @@ -52,6 +53,8 @@ extern INT16 sObjectSourceGridNo; extern WORLDITEM *pInventoryPoolList; extern INT32 iCurrentInventoryPoolPage; extern BOOLEAN fMapInventoryItemCompatable[ ]; +// WANNE 2 +extern MAP_INVENTORY_POOL_SLOT_COUNT; BOOLEAN IsMapScreenWorldItemInvisibleInMapInventory( WORLDITEM *pWorldItem ); BOOLEAN IsMapScreenWorldItemVisibleInMapInventory( WORLDITEM *pWorldItem ); diff --git a/Strategic/Map Screen Interface Map.cpp b/Strategic/Map Screen Interface Map.cpp index a2410fb5..db3e4c59 100644 --- a/Strategic/Map Screen Interface Map.cpp +++ b/Strategic/Map Screen Interface Map.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #include "GameSettings.h" @@ -42,7 +43,6 @@ #include "GameSettings.h" #endif - // zoom x and y coords for map scrolling INT32 iZoomX = 0; INT32 iZoomY = 0; @@ -74,14 +74,15 @@ INT32 iZoomY = 0; #define VERT_SCROLL 10 // the pop up for helicopter stuff -#define MAP_HELICOPTER_ETA_POPUP_X 400 -#define MAP_HELICOPTER_ETA_POPUP_Y 250 -#define MAP_HELICOPTER_UPPER_ETA_POPUP_Y 50 -#define MAP_HELICOPTER_ETA_POPUP_WIDTH 120 -#define MAP_HELICOPTER_ETA_POPUP_HEIGHT 68 +#define MAP_HELICOPTER_ETA_POPUP_X 400 +#define MAP_HELICOPTER_ETA_POPUP_Y 250 +#define MAP_HELICOPTER_UPPER_ETA_POPUP_Y 50 +#define MAP_HELICOPTER_ETA_POPUP_WIDTH 120 +#define MAP_HELICOPTER_ETA_POPUP_HEIGHT 68 -#define MAP_LEVEL_STRING_X 432 -#define MAP_LEVEL_STRING_Y 305 +// WANNE 2 +#define MAP_LEVEL_STRING_X (SCREEN_WIDTH - 208) //432 +#define MAP_LEVEL_STRING_Y (SCREEN_HEIGHT - 175) //305 // font #define MAP_FONT BLOCKFONT2 @@ -95,23 +96,25 @@ INT32 iZoomY = 0; //Map Location index regions +// WANNE 2 + +// WANNE 2 (The numbers above the map) // x start of hort index -#define MAP_HORT_INDEX_X 292 - +#define MAP_HORT_INDEX_X (MAP_BORDER_X + MAP_BORDER_X_OFFSET + 31)//(SCREEN_WIDTH - 348) //292 // y position of hort index -#define MAP_HORT_INDEX_Y 10 - +#define MAP_HORT_INDEX_Y (MAP_BORDER_Y + MAP_BORDER_Y_OFFSET + 8) // height of hort index -#define MAP_HORT_HEIGHT GetFontHeight(MAP_FONT) +#define MAP_HORT_HEIGHT GetFontHeight(MAP_FONT) + +// WANNE 2 (the letters on the left side of the map) // vert index start x -#define MAP_VERT_INDEX_X 273 - +#define MAP_VERT_INDEX_X (MAP_BORDER_X + MAP_BORDER_X_OFFSET + 13) //(SCREEN_WIDTH - 367) // 273 // vert index start y -#define MAP_VERT_INDEX_Y 31 - +#define MAP_VERT_INDEX_Y (MAP_BORDER_Y + MAP_BORDER_Y_OFFSET + 29) // vert width -#define MAP_VERT_WIDTH GetFontHeight(MAP_FONT) +#define MAP_VERT_WIDTH GetFontHeight(MAP_FONT) + // "Boxes" Icons #define SMALL_YELLOW_BOX 0 @@ -414,6 +417,7 @@ INT16 gpSamSectorX[] = { SAM_1_X, SAM_2_X, SAM_3_X, SAM_4_X }; INT16 gpSamSectorY[] = { SAM_1_Y, SAM_2_Y, SAM_3_Y, SAM_4_Y }; +// WANNE 2 (reinitialization in "DrawMap()") // map region SGPRect MapScreenRect={ (MAP_VIEW_START_X+MAP_GRID_X - 2), ( MAP_VIEW_START_Y+MAP_GRID_Y - 1), MAP_VIEW_START_X + MAP_VIEW_WIDTH - 1 + MAP_GRID_X , MAP_VIEW_START_Y+MAP_VIEW_HEIGHT-10+MAP_GRID_Y}; @@ -680,6 +684,17 @@ UINT32 DrawMap( void ) INT16 cnt, cnt2; INT32 iCounter = 0; + // WANNE 2 + //MAP_VIEW_START_X = (SCREEN_WIDTH - 370); + //MAP_VIEW_START_Y = 10; + + MapScreenRect.iLeft = MAP_VIEW_START_X+MAP_GRID_X - 2; + MapScreenRect.iTop = MAP_VIEW_START_Y+MAP_GRID_Y - 1; + MapScreenRect.iRight = MAP_VIEW_START_X + MAP_VIEW_WIDTH - 1 + MAP_GRID_X; + MapScreenRect.iBottom = MAP_VIEW_START_Y+MAP_VIEW_HEIGHT-10+MAP_GRID_Y; + + //MapScreenRect={ (MAP_VIEW_START_X+MAP_GRID_X - 2), ( MAP_VIEW_START_Y+MAP_GRID_Y - 1), MAP_VIEW_START_X + MAP_VIEW_WIDTH - 1 + MAP_GRID_X , MAP_VIEW_START_Y+MAP_VIEW_HEIGHT-10+MAP_GRID_Y}; + if( !iCurrentMapSectorZ ) { pDestBuf = (UINT16*)LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES); @@ -879,7 +894,8 @@ UINT32 DrawMap( void ) DisplayLevelString( ); - //RestoreClipRegionToFullScreen( ); + // WANNE 2 + RestoreClipRegionToFullScreen( ); return( TRUE ); } @@ -3961,7 +3977,10 @@ void ClipBlitsToMapViewRegionForRectangleAndABit( UINT32 uiDestPitchBYTES ) void RestoreClipRegionToFullScreenForRectangle( UINT32 uiDestPitchBYTES ) { // clip blits to map view region - SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, 640, 480 ); + //SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, 640, 480 ); + + // WANNE 2 + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); return; } @@ -4396,8 +4415,8 @@ void DisplayPositionOfHelicopter( void ) CHAR16 sString[ 4 ]; - AssertMsg( ( sOldMapX >= 0 ) && ( sOldMapX < 640 ), String( "DisplayPositionOfHelicopter: Invalid sOldMapX = %d", sOldMapX ) ); - AssertMsg( ( sOldMapY >= 0 ) && ( sOldMapY < 480 ), String( "DisplayPositionOfHelicopter: Invalid sOldMapY = %d", sOldMapY ) ); + AssertMsg( ( sOldMapX >= 0 ) && ( sOldMapX < SCREEN_WIDTH ), String( "DisplayPositionOfHelicopter: Invalid sOldMapX = %d", sOldMapX ) ); + AssertMsg( ( sOldMapY >= 0 ) && ( sOldMapY < SCREEN_HEIGHT ), String( "DisplayPositionOfHelicopter: Invalid sOldMapY = %d", sOldMapY ) ); // restore background on map where it is if( sOldMapX != 0 ) @@ -4471,10 +4490,11 @@ void DisplayPositionOfHelicopter( void ) } */ - AssertMsg( ( minX >= 0 ) && ( minX < 640 ), String( "DisplayPositionOfHelicopter: Invalid minX = %d", minX ) ); - AssertMsg( ( maxX >= 0 ) && ( maxX < 640 ), String( "DisplayPositionOfHelicopter: Invalid maxX = %d", maxX ) ); - AssertMsg( ( minY >= 0 ) && ( minY < 640 ), String( "DisplayPositionOfHelicopter: Invalid minY = %d", minY ) ); - AssertMsg( ( maxY >= 0 ) && ( maxY < 640 ), String( "DisplayPositionOfHelicopter: Invalid maxY = %d", maxY ) ); + // WANNE 2 + AssertMsg( ( minX >= 0 ) && ( minX < SCREEN_WIDTH ), String( "DisplayPositionOfHelicopter: Invalid minX = %d", minX ) ); + AssertMsg( ( maxX >= 0 ) && ( maxX < SCREEN_WIDTH ), String( "DisplayPositionOfHelicopter: Invalid maxX = %d", maxX ) ); + AssertMsg( ( minY >= 0 ) && ( minY < SCREEN_WIDTH ), String( "DisplayPositionOfHelicopter: Invalid minY = %d", minY ) ); + AssertMsg( ( maxY >= 0 ) && ( maxY < SCREEN_WIDTH ), String( "DisplayPositionOfHelicopter: Invalid maxY = %d", maxY ) ); // IMPORTANT: Since min can easily be larger than max, we gotta cast to as signed value x = ( UINT32 )( minX + flRatio * ( ( INT16 ) maxX - ( INT16 ) minX ) ); @@ -4494,10 +4514,11 @@ void DisplayPositionOfHelicopter( void ) } - AssertMsg( ( x >= 0 ) && ( x < 640 ), String( "DisplayPositionOfHelicopter: Invalid x = %d. At %d,%d. Next %d,%d. Min/Max X = %d/%d", + // WANNE 2 + AssertMsg( ( x >= 0 ) && ( x < SCREEN_WIDTH ), String( "DisplayPositionOfHelicopter: Invalid x = %d. At %d,%d. Next %d,%d. Min/Max X = %d/%d", x, pGroup->ubSectorX, pGroup->ubSectorY, pGroup->ubNextX, pGroup->ubNextY, minX, maxX ) ); - AssertMsg( ( y >= 0 ) && ( y < 480 ), String( "DisplayPositionOfHelicopter: Invalid y = %d. At %d,%d. Next %d,%d. Min/Max Y = %d/%d", + AssertMsg( ( y >= 0 ) && ( y < SCREEN_HEIGHT ), String( "DisplayPositionOfHelicopter: Invalid y = %d. At %d,%d. Next %d,%d. Min/Max Y = %d/%d", y, pGroup->ubSectorX, pGroup->ubSectorY, pGroup->ubNextX, pGroup->ubNextY, minY, maxY ) ); @@ -4540,8 +4561,9 @@ void DisplayDestinationOfHelicopter( void ) HVOBJECT hHandle; - AssertMsg( ( sOldMapX >= 0 ) && ( sOldMapX < 640 ), String( "DisplayDestinationOfHelicopter: Invalid sOldMapX = %d", sOldMapX ) ); - AssertMsg( ( sOldMapY >= 0 ) && ( sOldMapY < 480 ), String( "DisplayDestinationOfHelicopter: Invalid sOldMapY = %d", sOldMapY ) ); + // WANNE 2 + AssertMsg( ( sOldMapX >= 0 ) && ( sOldMapX < SCREEN_WIDTH ), String( "DisplayDestinationOfHelicopter: Invalid sOldMapX = %d", sOldMapX ) ); + AssertMsg( ( sOldMapY >= 0 ) && ( sOldMapY < SCREEN_HEIGHT ), String( "DisplayDestinationOfHelicopter: Invalid sOldMapY = %d", sOldMapY ) ); // restore background on map where it is if( sOldMapX != 0 ) @@ -4561,8 +4583,9 @@ void DisplayDestinationOfHelicopter( void ) x = MAP_VIEW_START_X + ( MAP_GRID_X * sMapX ) + 1; y = MAP_VIEW_START_Y + ( MAP_GRID_Y * sMapY ) + 3; - AssertMsg( ( x >= 0 ) && ( x < 640 ), String( "DisplayDestinationOfHelicopter: Invalid x = %d. Dest %d,%d", x, sMapX, sMapY ) ); - AssertMsg( ( y >= 0 ) && ( y < 480 ), String( "DisplayDestinationOfHelicopter: Invalid y = %d. Dest %d,%d", y, sMapX, sMapY ) ); + // WANNE 2 + AssertMsg( ( x >= 0 ) && ( x < SCREEN_WIDTH ), String( "DisplayDestinationOfHelicopter: Invalid x = %d. Dest %d,%d", x, sMapX, sMapY ) ); + AssertMsg( ( y >= 0 ) && ( y < SCREEN_HEIGHT ), String( "DisplayDestinationOfHelicopter: Invalid y = %d. Dest %d,%d", y, sMapX, sMapY ) ); // clip blits to mapscreen region ClipBlitsToMapViewRegion( ); @@ -5006,6 +5029,7 @@ void DisplayLevelString( void ) SetFontBackground( FONT_BLACK ); swprintf( sString, L"%s %d", sMapLevelString[ 0 ], iCurrentMapSectorZ ); + // WANNE 2 mprintf( MAP_LEVEL_STRING_X, MAP_LEVEL_STRING_Y, sString ); SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); diff --git a/Strategic/Map Screen Interface Map.h b/Strategic/Map Screen Interface Map.h index 01c3c0eb..bd2a7d98 100644 --- a/Strategic/Map Screen Interface Map.h +++ b/Strategic/Map Screen Interface Map.h @@ -1,3 +1,4 @@ +// WANNE 2 #ifndef _MAP_SCREEN_INTERFACE_MAP_H #define _MAP_SCREEN_INTERFACE_MAP_H @@ -155,12 +156,29 @@ enum { #define SOUTH_ZOOM_BOUND 324 #define NORTH_ZOOM_BOUND 36 +// WANNE 2 +// WANNE 2 (the starting top/left position of the background image +#define MAP_BORDER_X 261 +#define MAP_BORDER_Y 0 + + +// WANNE 2 +// WANNE 2 (the offset of the map border) +#define MAP_BORDER_X_OFFSET (((SCREEN_WIDTH - 261) - 380) / 2) +#define MAP_BORDER_Y_OFFSET (((SCREEN_HEIGHT - 121) - 360) / 2) + +// WANNE 2 // map view region -#define MAP_VIEW_START_X 270 -#define MAP_VIEW_START_Y 10 +#define MAP_VIEW_START_X (MAP_BORDER_X + MAP_BORDER_X_OFFSET + 9) +#define MAP_VIEW_START_Y (MAP_BORDER_Y + MAP_BORDER_Y_OFFSET + 10) #define MAP_VIEW_WIDTH 336 #define MAP_VIEW_HEIGHT 298 +//#define MAP_VIEW_START_X 270 +//#define MAP_VIEW_START_Y 10 +//#define MAP_VIEW_WIDTH 336 +//#define MAP_VIEW_HEIGHT 298 + // zoomed in grid sizes #define MAP_GRID_ZOOM_X MAP_GRID_X*2 #define MAP_GRID_ZOOM_Y MAP_GRID_Y*2 @@ -191,6 +209,9 @@ enum { // wait time until temp path is drawn, from placing cursor on a map grid #define MIN_WAIT_TIME_FOR_TEMP_PATH 200 +//extern INT32 MAP_VIEW_START_X; +//extern INT32 MAP_VIEW_START_Y; + // zoom UL coords extern INT32 iZoomX; diff --git a/Strategic/Map Screen Interface.cpp b/Strategic/Map Screen Interface.cpp index 155ed4ab..3c920b1b 100644 --- a/Strategic/Map Screen Interface.cpp +++ b/Strategic/Map Screen Interface.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #else @@ -40,8 +41,8 @@ #endif // inventory pool position on screen -#define MAP_INVEN_POOL_X 300 -#define MAP_INVEN_POOL_Y 300 +#define MAP_INVEN_POOL_X 300 +#define MAP_INVEN_POOL_Y 300 // the number of help region messages #define NUMBER_OF_MAPSCREEN_HELP_MESSAGES 5 @@ -49,7 +50,8 @@ // number of LINKED LISTS for sets of leave items (each slot holds an unlimited # of items) #define NUM_LEAVE_LIST_SLOTS 20 -#define SELECTED_CHAR_ARROW_X 8 +// WANNE 2 +#define SELECTED_CHAR_ARROW_X 1 //8 #define SIZE_OF_UPDATE_BOX 20 @@ -89,6 +91,8 @@ enum{ OTHER_REGION, }; +// WANNE 2 +UINT16 usVehicleY = 0; // waiting list for update box INT32 iUpdateBoxWaitingList[ MAX_CHARACTER_COUNT ]; @@ -1141,7 +1145,8 @@ INT32 DoMapMessageBoxWithRect( UINT8 ubStyle, INT16 *zString, UINT32 uiExitScree INT32 DoMapMessageBox( UINT8 ubStyle, INT16 * zString, UINT32 uiExitScreen, UINT16 usFlags, MSGBOX_CALLBACK ReturnCallback ) { - SGPRect CenteringRect= {0, 0, 640, INV_INTERFACE_START_Y }; + // WANNE 2 + SGPRect CenteringRect= {0, 0, SCREEN_WIDTH, INV_INTERFACE_START_Y }; // reset the highlighted line giHighLine = -1; @@ -1272,6 +1277,8 @@ void HandleDisplayOfSelectedMercArrows( void ) INT16 sYPosition = 0; HVOBJECT hHandle; UINT8 ubCount = 0; + INT16 usVehicleCount = 0; + // blit an arrow by the name of each merc in a selected list if( bSelectedInfoChar == -1 ) { @@ -1294,7 +1301,9 @@ void HandleDisplayOfSelectedMercArrows( void ) if( bSelectedInfoChar >= FIRST_VEHICLE ) { - sYPosition += 6; + // WANNE 2 + usVehicleCount = bSelectedInfoChar - FIRST_VEHICLE; + sYPosition = usVehicleY+( usVehicleCount * ( Y_SIZE + 2) ) - 1;; } @@ -1311,9 +1320,12 @@ void HandleDisplayOfSelectedMercArrows( void ) if( ( IsEntryInSelectedListSet( ubCount ) == TRUE ) || ( ( bSelectedDestChar != - 1 ) ? ( ( Menptr[ gCharactersList[ ubCount ].usSolID ].ubGroupID != 0 ) ? ( Menptr[ gCharactersList[ bSelectedDestChar ].usSolID ].ubGroupID == Menptr[ gCharactersList[ ubCount ].usSolID ].ubGroupID ) : FALSE ) : FALSE ) ) { sYPosition = Y_START+( ubCount * ( Y_SIZE + 2) ) - 1; + if( ubCount >= FIRST_VEHICLE ) { - sYPosition += 6; + // WANNE 2 + usVehicleCount = ubCount - FIRST_VEHICLE; + sYPosition = usVehicleY+( usVehicleCount * ( Y_SIZE + 2) ) - 1;; } GetVideoObject( &hHandle, guiSelectedCharArrow ); @@ -4758,17 +4770,12 @@ void DisplaySoldierUpdateBox( ) iUpdatePanelHeight = ( iNumberHigh + 1 ) * TACT_HEIGHT_OF_UPDATE_PANEL_BLOCKS; - // get the x,y offsets on the screen of the panel - iX = 290 + ( 336 - iUpdatePanelWidth ) / 2; - -// iY = 28 + ( 288 - iUpdatePanelHeight ) / 2; - - // Have the bottom of the box ALWAYS a set distance from the bottom of the map ( so user doesnt have to move mouse far ) - iY = 280 - iUpdatePanelHeight; + // WANNE 2 + iX = (MAP_BORDER_X + ((SCREEN_WIDTH - MAP_BORDER_X) / 2)) - (iUpdatePanelWidth / 2); + iY = (MAP_BORDER_Y + ((SCREEN_HEIGHT - 121) / 2)) - (iUpdatePanelHeight / 2); GetVideoObject( &hBackGroundHandle, guiUpdatePanelTactical ); - //Display the 2 TOP corner pieces BltVideoObject( guiSAVEBUFFER, hBackGroundHandle, 0, iX-4, iY - 4 , VO_BLT_SRCTRANSPARENCY,NULL ); BltVideoObject( guiSAVEBUFFER, hBackGroundHandle, 2, iX+iUpdatePanelWidth, iY - 4 , VO_BLT_SRCTRANSPARENCY,NULL ); @@ -4864,6 +4871,7 @@ void DisplaySoldierUpdateBox( ) } + // WANNE 2 //Display the reason for the update box if( fFourWideMode ) { @@ -4887,6 +4895,7 @@ void DisplaySoldierUpdateBox( ) } +// WANNE 2 void CreateDestroyUpdatePanelButtons(INT32 iX, INT32 iY, BOOLEAN fFourWideMode ) { static BOOLEAN fCreated = FALSE; @@ -6435,7 +6444,6 @@ void HandleBlitOfSectorLocatorIcon( INT16 sSectorX, INT16 sSectorY, INT16 sSecto // invalidate region on frame buffer InvalidateRegion( sScreenX, sScreenY - 1, sScreenX + MAP_GRID_X , sScreenY + MAP_GRID_Y ); - } diff --git a/Strategic/Map Screen Interface.h b/Strategic/Map Screen Interface.h index f9f4a0aa..dff205d9 100644 --- a/Strategic/Map Screen Interface.h +++ b/Strategic/Map Screen Interface.h @@ -48,7 +48,7 @@ typedef struct FASTHELPREGION { #define MAP_SCREEN_FONT BLOCKFONT2 // characterlist regions -#define Y_START 146 +#define Y_START 135 //146 #define MAP_START_KEYRING_Y 107 #define Y_SIZE GetFontHeight(MAP_SCREEN_FONT) diff --git a/Strategic/Map Screen Interface_NEW.cpp b/Strategic/Map Screen Interface_NEW.cpp new file mode 100644 index 00000000..ffb13882 --- /dev/null +++ b/Strategic/Map Screen Interface_NEW.cpp @@ -0,0 +1,6482 @@ +// WANNE 2 +#ifdef PRECOMPILEDHEADERS + #include "Strategic All.h" +#else + #include "Map Screen Interface.h" + #include "string.h" + #include "Map Screen Interface Map.h" + #include "Render Dirty.h" + #include "Font Control.h" + #include "Assignments.h" + #include "Soldier Control.h" + #include "Overhead.h" + #include "Squads.h" + #include "Sound Control.h" + #include "Soundman.h" + #include "Message.h" + #include "PopUpBox.h" + #include "Game Clock.h" + #include "Handle Items.h" + #include "Interface Items.h" + #include "Isometric Utils.h" + #include "Interface.h" + #include "Game Event Hook.h" + #include "Tactical Save.h" + #include "Quests.h" + #include "Strategicmap.h" + #include "Soldier Profile.h" + #include "Strategic Movement.h" + #include "Dialogue Control.h" + #include "Map Screen Interface Border.h" + #include "Map Screen Interface Bottom.h" + #include "Vehicles.h" + #include "LINE.H" + #include "Text.h" + #include "gameloop.h" + #include "Map Screen Helicopter.h" + #include "PreBattle Interface.h" + #include "WordWrap.h" + #include "interface control.h" + #include "GameSettings.h" +#endif + +// inventory pool position on screen +#define MAP_INVEN_POOL_X 300 +#define MAP_INVEN_POOL_Y 300 + +// the number of help region messages +#define NUMBER_OF_MAPSCREEN_HELP_MESSAGES 5 + +// number of LINKED LISTS for sets of leave items (each slot holds an unlimited # of items) +#define NUM_LEAVE_LIST_SLOTS 20 + +// WANNE 2 +#define SELECTED_CHAR_ARROW_X 1 //8 + +#define SIZE_OF_UPDATE_BOX 20 + +// as deep as the map goes +#define MAX_DEPTH_OF_MAP 3 + + +// number of merc columns for four wide mode +#define NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE 4 + +// number of merc columns for 2 wide mode +#define NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE 2 + +// number needed for 4 wide mode to activate +#define NUMBER_OF_MERCS_FOR_FOUR_WIDTH_UPDATE_PANEL 4 + +#define DBL_CLICK_DELAY_FOR_MOVE_MENU 200 + + +#define TIMER_FOR_SHOW_EXIT_TO_TACTICAL_MESSAGE 15000 + +#define REASON_FOR_SOLDIER_UPDATE_OFFSET_Y (14) + +#define MAX_MAPSCREEN_FAST_HELP 100 + +#define VEHICLE_ONLY FALSE +#define AND_ALL_ON_BOARD TRUE + + +// the regions int he movemenu +enum{ + SQUAD_REGION = 0, + VEHICLE_REGION, + SOLDIER_REGION, + DONE_REGION, + CANCEL_REGION, + OTHER_REGION, +}; + +// WANNE 2 +UINT16 usVehicleY = 0; + +// waiting list for update box +INT32 iUpdateBoxWaitingList[ MAX_CHARACTER_COUNT ]; + +FASTHELPREGION pFastHelpMapScreenList[ MAX_MAPSCREEN_FAST_HELP ]; + +// the move menu region +MOUSE_REGION gMoveMenuRegion[ MAX_POPUP_BOX_STRING_COUNT ]; + +MOUSE_REGION gMapScreenHelpTextMask; + +BOOLEAN fShowMapScreenHelpText = FALSE; +BOOLEAN fScreenMaskForMoveCreated = FALSE; +BOOLEAN fLockOutMapScreenInterface = FALSE; + +extern INT32 giMercPanelImage; +extern BOOLEAN fShowDescriptionFlag; +extern BOOLEAN fInMapMode; +extern GROUP *gpBattleGroup; + +CHAR16 gsCustomErrorString[ 128 ]; + +BOOLEAN fShowUpdateBox = FALSE; +BOOLEAN fInterfaceFastHelpTextActive = FALSE; +BOOLEAN fReBuildCharacterList = FALSE; +INT32 giSizeOfInterfaceFastHelpTextList = 0; + +//Animated sector locator icon variables. +INT16 gsSectorLocatorX; +INT16 gsSectorLocatorY; +UINT8 gubBlitSectorLocatorCode; //color +UINT32 guiSectorLocatorGraphicID; //icon graphic ID +// the animate time per frame in milliseconds +#define ANIMATED_BATTLEICON_FRAME_TIME 80 +#define MAX_FRAME_COUNT_FOR_ANIMATED_BATTLE_ICON 12 + + + +SGPPoint pMapScreenFastHelpLocationList[]={ + { 25,200 }, + { 150,200 }, + { 450,430 }, + { 400,200 }, + { 250,100 }, + { 100,100 }, + { 100,100 }, + { 100,100 }, + { 100,100 }, + { 150,200 }, + { 100,100 }, +}; + +INT32 pMapScreenFastHelpWidthList[]={ + 100, + 100, + 100, + 100, + 100, + 100, + 100, + 100, + 100, + 300, +}; + +// number of mercs in sector capable of moving +INT32 giNumberOfSoldiersInSectorMoving = 0; + +// number of squads capable of moving +INT32 giNumberOfSquadsInSectorMoving = 0; + +// number of vehicles in sector moving +INT32 giNumberOfVehiclesInSectorMoving = 0; + +INT32 iHeightOfInitFastHelpText = 0; + +extern INT32 giMapContractButton; +extern INT32 giCharInfoButton[]; +extern STR16 pUpdatePanelButtons[]; + +// the list of soldiers that are moving +SOLDIERTYPE * pSoldierMovingList[ MAX_CHARACTER_COUNT ]; +BOOLEAN fSoldierIsMoving[ MAX_CHARACTER_COUNT ]; + +SOLDIERTYPE *pUpdateSoldierBox[ SIZE_OF_UPDATE_BOX ]; + +INT32 giUpdateSoldierFaces[ SIZE_OF_UPDATE_BOX ]; + +// the squads thata re moving +INT32 iSquadMovingList[ NUMBER_OF_SQUADS ]; +INT32 fSquadIsMoving[ NUMBER_OF_SQUADS ]; + +// the vehicles thata re moving +INT32 iVehicleMovingList[ NUMBER_OF_SQUADS ]; +INT32 fVehicleIsMoving[ NUMBER_OF_SQUADS ]; + +MOUSE_REGION gMoveBoxScreenMask; + +// the save buffer +extern UINT32 guiSAVEBUFFER; + +extern BOOLEAN fShowInventoryFlag; +extern FACETYPE *gpCurrentTalkingFace; +extern UINT8 gubCurrentTalkingID; +extern BOOLEAN fMapScreenBottomDirty; +extern MOUSE_REGION gMPanelRegion; + + +// has the inventory pool been selected to be on or off? +BOOLEAN fMapInventoryPoolInited = FALSE; +BOOLEAN fShowMapScreenMovementList = FALSE; + + +MapScreenCharacterSt gCharactersList[ MAX_CHARACTER_COUNT+1]; + +extern MOUSE_REGION gCharInfoHandRegion; +MOUSE_REGION gMapStatusBarsRegion; + +SGPPoint MovePosition={450, 100 }; + +// which lines are selected? .. for assigning groups of mercs to the same thing +BOOLEAN fSelectedListOfMercsForMapScreen[ MAX_CHARACTER_COUNT ]; +BOOLEAN fResetTimerForFirstEntryIntoMapScreen = FALSE; +INT32 iReasonForSoldierUpDate = NO_REASON_FOR_UPDATE; + +// sam and mine icons +UINT32 guiSAMICON; + + +// disable team info panels due to battle roster +BOOLEAN fDisableDueToBattleRoster = FALSE; + +// track old contract times +INT32 iOldContractTimes[ MAX_CHARACTER_COUNT ]; + +// position of pop up box +INT32 giBoxY = 0; + +// screen mask for inventory pop up +MOUSE_REGION gInventoryScreenMask; + +MOUSE_REGION gContractIconRegion; +MOUSE_REGION gInsuranceIconRegion; +MOUSE_REGION gDepositIconRegion; + +// general line..current and old +INT32 giHighLine=-1; + +// assignment's line...glow box +INT32 giAssignHighLine=-1; + +// destination plot line....glow box +INT32 giDestHighLine=-1; + +// contract selection glow box +INT32 giContractHighLine = -1; + +// the sleep column glow box +INT32 giSleepHighLine = -1; + +// pop up box textures +UINT32 guiPOPUPTEX; +UINT32 guiPOPUPBORDERS; + +// the currently selected character arrow +UINT32 guiSelectedCharArrow; + +INT32 guiUpdatePanelButtonsImage[ 2 ]; +INT32 guiUpdatePanelButtons[ 2 ]; + +// the update panel +UINT32 guiUpdatePanel; +UINT32 guiUpdatePanelTactical; + +// the leave item list +MERC_LEAVE_ITEM *gpLeaveListHead[ NUM_LEAVE_LIST_SLOTS ]; + +// holds ids of mercs who left stuff behind +UINT32 guiLeaveListOwnerProfileId[ NUM_LEAVE_LIST_SLOTS ]; + +// flag to reset contract region glow +BOOLEAN fResetContractGlow = FALSE; + +// timers for double click +INT32 giDblClickTimersForMoveBoxMouseRegions[ MAX_POPUP_BOX_STRING_COUNT ]; + +INT32 giExitToTactBaseTime = 0; +UINT32 guiSectorLocatorBaseTime = 0; + + +// which menus are we showing +BOOLEAN fShowAssignmentMenu = FALSE; +BOOLEAN fShowTrainingMenu = FALSE; +BOOLEAN fShowAttributeMenu = FALSE; +BOOLEAN fShowSquadMenu = FALSE; +BOOLEAN fShowContractMenu = FALSE; +BOOLEAN fShowRemoveMenu = FALSE; + +BOOLEAN fRebuildMoveBox = FALSE; + +// positions for all the pop up boxes +SGPRect ContractDimensions={0,0,140,60}; +SGPPoint ContractPosition={120,50}; +SGPRect AttributeDimensions={0,0,100,95}; +SGPPoint AttributePosition={220,150}; +SGPRect TrainDimensions={0,0,100,95}; +SGPPoint TrainPosition={160,150}; +SGPRect VehicleDimensions={0,0,80,60}; +SGPPoint VehiclePosition={160,150}; + +SGPPoint RepairPosition={160,150}; +SGPRect RepairDimensions={0,0,80,80}; + +SGPRect AssignmentDimensions = { 0,0, 100, 95}; +SGPPoint AssignmentPosition = { 120, 150 }; +SGPPoint SquadPosition ={ 160, 150 }; +SGPRect SquadDimensions ={ 0, 0, 140, 60 }; + +SGPPoint OrigContractPosition={120,50}; +SGPPoint OrigAttributePosition={220,150}; +SGPPoint OrigSquadPosition ={ 160, 150 }; +SGPPoint OrigAssignmentPosition = { 120, 150 }; +SGPPoint OrigTrainPosition={160,150}; +SGPPoint OrigVehiclePosition={160,150}; + +//extern BOOLEAN fMapExitDueToMessageBox; + +// at least one merc was hired at some time +BOOLEAN gfAtLeastOneMercWasHired = FALSE; + +// rebuild contract box this character +extern void RebuildContractBoxForMerc( SOLDIERTYPE *pCharacter ); + +extern void SetUpCursorForStrategicMap( void ); + +extern void MapScreenDefaultOkBoxCallback( UINT8 bExitValue ); + +extern BOOLEAN PlayerSoldierTooTiredToTravel( SOLDIERTYPE *pSoldier ); + +extern void RememberPreviousPathForAllSelectedChars( void ); + + +// the screen mask functions +void CreateScreenMaskForInventoryPoolPopUp( void ); +void RemoveScreenMaskForInventoryPoolPopUp( void ); +void InventoryScreenMaskBtnCallback(MOUSE_REGION * pRegion, INT32 iReason ); + +void MapScreenHelpTextScreenMaskBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ); +void SetUpShutDownMapScreenHelpTextScreenMask( void ); +void DisplayFastHelpRegions( FASTHELPREGION *pRegion, INT32 iSize ); +void DisplayUserDefineHelpTextRegions( FASTHELPREGION *pRegion ); + + +// how many people does the player have? +//INT32 GetNumberOfCharactersOnPlayersTeam( void ); + +void AddStringsToMoveBox( void ); +void CreatePopUpBoxForMovementBox( void ); +void MoveMenuMvtCallback(MOUSE_REGION * pRegion, INT32 iReason ); +void MoveMenuBtnCallback(MOUSE_REGION * pRegion, INT32 iReason ); +void SelectAllOtherSoldiersInList( void ); +void DeselectAllOtherSoldiersInList( void ); +void HandleMoveoutOfSectorMovementTroops( void ); +void HandleSettingTheSelectedListOfMercs( void ); +void BuildMouseRegionsForMoveBox( void ); +INT32 HowManyMovingSoldiersInVehicle( INT32 iVehicleId ); +INT32 HowManyMovingSoldiersInSquad( INT32 iSquadNumber ); +void ClearMouseRegionsForMoveBox( void ); +BOOLEAN AllOtherSoldiersInListAreSelected( void ); +BOOLEAN AllSoldiersInSquadSelected( INT32 iSquadNumber ); + +void MoveScreenMaskBtnCallback(MOUSE_REGION * pRegion, INT32 iReason ); +/* +void CreateUpdateBoxStrings( void ); +void CreateUpdateBox( void ); +void RemoveUpdateBox( void ); +void DisplayUpdateBox( void ); +*/ +void CreateDestroyUpdatePanelButtons(INT32 iX, INT32 iY, BOOLEAN fFourWideMode ); +void RenderSoldierSmallFaceForUpdatePanel( INT32 iIndex, INT32 iX, INT32 iY ); +void ContinueUpdateButtonCallback(GUI_BUTTON *btn,INT32 reason); +void StopUpdateButtonCallback(GUI_BUTTON *btn,INT32 reason); +//INT32 GetSquadListIndexForSquadNumber( INT32 iSquadNumber ); +INT8 FindSquadThatSoldierCanJoin( SOLDIERTYPE *pSoldier ); +BOOLEAN CanSoldierMoveWithVehicleId( SOLDIERTYPE *pSoldier, INT32 iVehicle1Id ); +BOOLEAN IsAnythingSelectedForMoving( void ); +BOOLEAN CanMoveBoxSoldierMoveStrategically( SOLDIERTYPE *pSoldier, BOOLEAN fShowErrorMessage ); + +BOOLEAN ValidSelectableCharForNextOrPrev( INT32 iNewCharSlot ); + +extern void ResumeOldAssignment( SOLDIERTYPE *pSoldier ); + + + +void InitalizeVehicleAndCharacterList( void ) +{ + // will init the vehicle and character lists to zero + memset(&gCharactersList, 0, sizeof( gCharactersList )); + + return; +} + + +void SetEntryInSelectedCharacterList( INT8 bEntry ) +{ + Assert( ( bEntry >= 0 ) && ( bEntry < MAX_CHARACTER_COUNT ) ); + + // set this entry to selected + fSelectedListOfMercsForMapScreen[ bEntry ] = TRUE ; + + return; +} + +void ResetEntryForSelectedList( INT8 bEntry ) +{ + Assert( ( bEntry >= 0 ) && ( bEntry < MAX_CHARACTER_COUNT ) ); + + // set this entry to selected + fSelectedListOfMercsForMapScreen[ bEntry ] = FALSE; + + return; +} + +void ResetSelectedListForMapScreen( void ) +{ + // set all the entries int he selected list to false + memset( &fSelectedListOfMercsForMapScreen, FALSE, MAX_CHARACTER_COUNT * sizeof( BOOLEAN ) ); + + // if we still have a valid dude selected + if ( ( bSelectedInfoChar != -1 ) && ( gCharactersList[ bSelectedInfoChar ].fValid == TRUE ) ) + { + // then keep him selected + SetEntryInSelectedCharacterList( bSelectedInfoChar ); + } + + return; +} + + +BOOLEAN IsEntryInSelectedListSet( INT8 bEntry ) +{ + Assert( ( bEntry >= 0 ) && ( bEntry < MAX_CHARACTER_COUNT ) ); + + // is this entry in the selected list set? + + return( fSelectedListOfMercsForMapScreen[ bEntry ] ); + +} + + +void ToggleEntryInSelectedList( INT8 bEntry ) +{ + Assert( ( bEntry >= 0 ) && ( bEntry < MAX_CHARACTER_COUNT ) ); + + // toggle the value in the selected list + fSelectedListOfMercsForMapScreen[ bEntry ] = !( fSelectedListOfMercsForMapScreen[ bEntry ] ); + + return; +} + +void BuildSelectedListFromAToB( INT8 bA, INT8 bB ) +{ + INT8 bStart =0, bEnd = 0; + + // run from a to b..set slots as selected + + if( bA > bB ) + { + bStart = bB; + bEnd = bA; + } + else + { + bStart = bA; + bEnd = bB; + } + + // run through list and set all intermediaries to true + + for( bStart; bStart <= bEnd; bStart++ ) + { + SetEntryInSelectedCharacterList( bStart ); + } + + return; +} + + +BOOLEAN MultipleCharacterListEntriesSelected( void ) +{ + UINT8 ubSelectedCnt = 0; + INT32 iCounter = 0; + + // check if more than one person is selected in the selected list + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + if( fSelectedListOfMercsForMapScreen[iCounter] == TRUE ) + { + ubSelectedCnt++; + } + } + + if( ubSelectedCnt > 1 ) + { + return( TRUE ); + } + else + { + return( FALSE ); + } +} + + + +void ResetAssignmentsForMercsTrainingUnpaidSectorsInSelectedList( INT8 bAssignment ) +{ + INT32 iCounter = 0; + SOLDIERTYPE *pSoldier = NULL; + + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + // valid character? + if( gCharactersList[ iCounter ].fValid == FALSE ) + { + // nope + continue; + } + + pSoldier = &Menptr[ gCharactersList[ iCounter ].usSolID ]; + + if( pSoldier->bActive == FALSE ) + { + continue; + } + + if( pSoldier->bAssignment == TRAIN_TOWN ) + { + if ( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ].fMilitiaTrainingPaid == FALSE ) + { + ResumeOldAssignment( pSoldier ); + } + } + } +} + + +void ResetAssignmentOfMercsThatWereTrainingMilitiaInThisSector( INT16 sSectorX, INT16 sSectorY ) +{ + INT32 iCounter = 0; + SOLDIERTYPE *pSoldier = NULL; + + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + // valid character? + if( gCharactersList[ iCounter ].fValid == FALSE ) + { + // nope + continue; + } + + pSoldier = &Menptr[ gCharactersList[ iCounter ].usSolID ]; + + if( pSoldier->bActive == FALSE ) + { + continue; + } + + if( pSoldier->bAssignment == TRAIN_TOWN ) + { + if( ( pSoldier->sSectorX == sSectorX ) && ( pSoldier->sSectorY == sSectorY ) && ( pSoldier->bSectorZ == 0 ) ) + { + ResumeOldAssignment( pSoldier ); + } + } + } +} + + + +/* +void PlotPathForSelectedCharacterList( INT16 sX, INT16 sY ) +{ + INT32 iCounter = 0; + // run through list and build paths for each character + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + if( ( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE )&&( bSelectedDestChar != iCounter ) ) + { + // character is valid.. do this for every one not the bSelectedDestChar + PlotPathForCharacter( &Menptr[ gCharactersList[ iCounter ].usSolID ], sX, sY, FALSE ); + } + } +} +*/ + + +// check if the members of the selected list move with this guy... are they in the same mvt group? +void DeselectSelectedListMercsWhoCantMoveWithThisGuy( SOLDIERTYPE *pSoldier ) +{ + INT32 iCounter = 0; + SOLDIERTYPE *pSoldier2 = NULL; + + + // deselect any other selected mercs that can't travel together with pSoldier + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + if( gCharactersList[ iCounter ].fValid == TRUE ) + { + if( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE ) + { + pSoldier2 = &( Menptr[ gCharactersList[ iCounter ].usSolID ] ); + + // skip the guy we are + if ( pSoldier == pSoldier2 ) + { + continue; + } + + + // NOTE ABOUT THE VEHICLE TESTS BELOW: + // Vehicles and foot squads can't plot movement together! + // The ETAs are different, and unlike squads, vehicles can't travel everywhere! + // However, different vehicles CAN plot together, since they all travel at the same rates now + + // if anchor guy is IN a vehicle + if( pSoldier->bAssignment == VEHICLE ) + { + if ( !CanSoldierMoveWithVehicleId( pSoldier2, pSoldier->iVehicleId ) ) + { + // reset entry for selected list + ResetEntryForSelectedList( ( INT8 )iCounter ); + } + } + // if anchor guy IS a vehicle + else if ( pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) + { + if ( !CanSoldierMoveWithVehicleId( pSoldier2, pSoldier->bVehicleID ) ) + { + // reset entry for selected list + ResetEntryForSelectedList( ( INT8 )iCounter ); + } + } + // if this guy is IN a vehicle + else if( pSoldier2->bAssignment == VEHICLE ) + { + if ( !CanSoldierMoveWithVehicleId( pSoldier, pSoldier2->iVehicleId ) ) + { + // reset entry for selected list + ResetEntryForSelectedList( ( INT8 )iCounter ); + } + } + // if this guy IS a vehicle + else if ( pSoldier2->uiStatusFlags & SOLDIER_VEHICLE ) + { + if ( !CanSoldierMoveWithVehicleId( pSoldier, pSoldier2->bVehicleID ) ) + { + // reset entry for selected list + ResetEntryForSelectedList( ( INT8 )iCounter ); + } + } + // reject those not a squad (vehicle handled above) + else if( pSoldier2->bAssignment >= ON_DUTY ) + { + ResetEntryForSelectedList( ( INT8 )iCounter ); + } + else + { + // reject those not in the same sector + if( ( pSoldier->sSectorX != pSoldier2->sSectorX ) || + ( pSoldier->sSectorY != pSoldier2->sSectorY ) || + ( pSoldier->bSectorZ != pSoldier2->bSectorZ ) ) + { + ResetEntryForSelectedList( ( INT8 )iCounter ); + } + + // if either is between sectors, they must be in the same movement group + if ( ( pSoldier->fBetweenSectors || pSoldier2->fBetweenSectors ) && + ( pSoldier->ubGroupID != pSoldier2->ubGroupID ) ) + { + ResetEntryForSelectedList( ( INT8 )iCounter ); + } + } + + // different movement groups in same sector is OK, even if they're not travelling together + } + } + } + + return; +} + + + +void SelectUnselectedMercsWhoMustMoveWithThisGuy( void ) +{ + INT32 iCounter = 0; + SOLDIERTYPE *pSoldier = NULL; + + + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + if( gCharactersList[ iCounter ].fValid == TRUE ) + { + // if not already selected + if( fSelectedListOfMercsForMapScreen[ iCounter ] == FALSE ) + { + pSoldier = &( Menptr[ gCharactersList[ iCounter ].usSolID ] ); + + // if on a squad or in a vehicle + if ( ( pSoldier->bAssignment < ON_DUTY ) || ( pSoldier->bAssignment == VEHICLE ) ) + { + // and a member of that squad or vehicle is selected + if ( AnyMercInSameSquadOrVehicleIsSelected( pSoldier ) ) + { + // then also select this guy + SetEntryInSelectedCharacterList( ( INT8 ) iCounter ); + } + } + } + } + } +} + + + +BOOLEAN AnyMercInSameSquadOrVehicleIsSelected( SOLDIERTYPE *pSoldier ) +{ + INT32 iCounter = 0; + SOLDIERTYPE *pSoldier2 = NULL; + + + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + if( gCharactersList[ iCounter ].fValid == TRUE ) + { + // if selected + if( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE ) + { + pSoldier2 = &( Menptr[ gCharactersList[ iCounter ].usSolID ] ); + + // if they have the same assignment + if( pSoldier->bAssignment == pSoldier2->bAssignment ) + { + // same squad? + if ( pSoldier->bAssignment < ON_DUTY ) + { + return ( TRUE ); + } + + // same vehicle? + if ( ( pSoldier->bAssignment == VEHICLE ) && ( pSoldier->iVehicleId == pSoldier2->iVehicleId ) ) + { + return ( TRUE ); + } + } + + // target guy is in a vehicle, and this guy IS that vehicle + if( ( pSoldier->bAssignment == VEHICLE ) && ( pSoldier2->uiStatusFlags & SOLDIER_VEHICLE ) && + ( pSoldier->iVehicleId == pSoldier2->bVehicleID ) ) + { + return ( TRUE ); + } + + // this guy is in a vehicle, and the target guy IS that vehicle + if( ( pSoldier2->bAssignment == VEHICLE ) && ( pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) && + ( pSoldier2->iVehicleId == pSoldier->bVehicleID ) ) + { + return ( TRUE ); + } + } + } + } + + return ( FALSE ); +} + + + +void RestoreBackgroundForAssignmentGlowRegionList( void ) +{ + static INT32 iOldAssignmentLine = -1; + + // will restore the background region of the assignment list after a glow has ceased + // ( a _LOST_MOUSE reason to the assignment region mvt callback handler ) + + if( fShowAssignmentMenu == TRUE ) + { + // force update + ForceUpDateOfBox( ghAssignmentBox ); + ForceUpDateOfBox( ghEpcBox ); + ForceUpDateOfBox( ghRemoveMercAssignBox ); + if( fShowSquadMenu == TRUE ) + { + ForceUpDateOfBox( ghSquadBox ); + } + else if( fShowTrainingMenu == TRUE ) + { + ForceUpDateOfBox( ghTrainingBox ); + } + + } + + if( fDisableDueToBattleRoster ) + { + return; + } + + if( iOldAssignmentLine != giAssignHighLine ) + { + // restore background + RestoreExternBackgroundRect( 66, Y_START - 1, 118 + 1 - 67, ( INT16 )( ( ( MAX_CHARACTER_COUNT + 1 ) * ( Y_SIZE + 2 ) ) + 1 ) ); + + // ARM: not good enough! must reblit the whole panel to erase glow chunk restored by help text disappearing!!! + fTeamPanelDirty = TRUE; + + // set old to current + iOldAssignmentLine = giAssignHighLine; + } + + // leave + return; +} + +void RestoreBackgroundForDestinationGlowRegionList( void ) +{ + static INT32 iOldDestinationLine = -1; + + // will restore the background region of the destinationz list after a glow has ceased + // ( a _LOST_MOUSE reason to the assignment region mvt callback handler ) + + if( fDisableDueToBattleRoster ) + { + return; + } + + if( iOldDestinationLine != giDestHighLine ) + { + // restore background + RestoreExternBackgroundRect( 182, Y_START - 1, 217 + 1 - 182, ( INT16 )( ( ( MAX_CHARACTER_COUNT + 1 ) * ( Y_SIZE + 2 ) ) + 1 ) ); + + // ARM: not good enough! must reblit the whole panel to erase glow chunk restored by help text disappearing!!! + fTeamPanelDirty = TRUE; + + // set old to current + iOldDestinationLine = giDestHighLine; + } + + // leave + return; +} + +void RestoreBackgroundForContractGlowRegionList( void ) +{ + static INT32 iOldContractLine = -1; + + // will restore the background region of the destinationz list after a glow has ceased + // ( a _LOST_MOUSE reason to the assignment region mvt callback handler ) + + if( fDisableDueToBattleRoster ) + { + return; + } + + if( iOldContractLine != giContractHighLine ) + { + // restore background + RestoreExternBackgroundRect( 222, Y_START - 1, 250 + 1 - 222, ( INT16 )( ( ( MAX_CHARACTER_COUNT + 1 ) * ( Y_SIZE + 2 ) ) + 1 ) ) ; + + // ARM: not good enough! must reblit the whole panel to erase glow chunk restored by help text disappearing!!! + fTeamPanelDirty = TRUE; + + // set old to current + iOldContractLine = giContractHighLine; + + // reset color rotation + fResetContractGlow = TRUE; + } + + // leave + return; +} + + +void RestoreBackgroundForSleepGlowRegionList( void ) +{ + static INT32 iOldSleepHighLine = -1; + + // will restore the background region of the destinations list after a glow has ceased + // ( a _LOST_MOUSE reason to the assignment region mvt callback handler ) + + if( fDisableDueToBattleRoster ) + { + return; + } + + if( iOldSleepHighLine != giSleepHighLine ) + { + // restore background + RestoreExternBackgroundRect( 123, Y_START - 1, 142 + 1 - 123, ( INT16 )( ( ( MAX_CHARACTER_COUNT + 1 ) * ( Y_SIZE + 2 ) ) + 1 ) ) ; + + // ARM: not good enough! must reblit the whole panel to erase glow chunk restored by help text disappearing!!! + fTeamPanelDirty = TRUE; + + // set old to current + iOldSleepHighLine = giSleepHighLine; + + // reset color rotation + fResetContractGlow = TRUE; + } + + // leave + return; +} + +void PlayGlowRegionSound( void ) +{ + // play a new message sound, if there is one playing, do nothing + static UINT32 uiSoundId = 0; + + if( uiSoundId != 0 ) + { + // is sound playing?..don't play new one + if( SoundIsPlaying( uiSoundId ) == TRUE ) + { + return; + } + } + + // otherwise no sound playing, play one + uiSoundId = PlayJA2SampleFromFile( "Sounds\\glowclick.wav", RATE_11025, MIDVOLUME, 1 , MIDDLEPAN ); + + return; +} + + + +INT16 CharacterIsGettingPathPlotted( INT16 sCharNumber ) +{ + // valid character number? + if( ( sCharNumber < 0 ) || ( sCharNumber >= MAX_CHARACTER_COUNT ) ) + { + return( FALSE ); + } + + // is the character a valid one? + if( gCharactersList[ sCharNumber ].fValid == FALSE ) + { + return ( FALSE ); + } + + // if the highlighted line character is also selected + if ( ( ( giDestHighLine != -1 ) && IsEntryInSelectedListSet ( ( INT8 ) giDestHighLine ) ) || + ( ( bSelectedDestChar != -1 ) && IsEntryInSelectedListSet ( bSelectedDestChar ) ) ) + { + // then ALL selected lines will be affected + if( IsEntryInSelectedListSet( ( INT8 ) sCharNumber ) ) + { + return( TRUE ); + } + } + else + { + // if he is *the* selected dude + if( bSelectedDestChar == sCharNumber ) + { + return ( TRUE ); + } + + // ONLY the highlighted line will be affected + if ( sCharNumber == giDestHighLine ) + { + return( TRUE ); + } + } + + return ( FALSE ); +} + +BOOLEAN IsCharacterSelectedForAssignment( INT16 sCharNumber ) +{ + // valid character number? + if( ( sCharNumber < 0 ) || ( sCharNumber >= MAX_CHARACTER_COUNT ) ) + { + return( FALSE ); + } + + // is the character a valid one? + if( gCharactersList[ sCharNumber ].fValid == FALSE ) + { + return ( FALSE ); + } + + // if the highlighted line character is also selected + if ( ( giAssignHighLine != -1 ) && IsEntryInSelectedListSet ( ( INT8 ) giAssignHighLine ) ) + { + // then ALL selected lines will be affected + if( IsEntryInSelectedListSet( ( INT8 ) sCharNumber ) ) + { + return( TRUE ); + } + } + else + { + // ONLY the highlighted line will be affected + if ( sCharNumber == giAssignHighLine ) + { + return( TRUE ); + } + } + + return( FALSE ); +} + + + +BOOLEAN IsCharacterSelectedForSleep( INT16 sCharNumber ) +{ + // valid character number? + if( ( sCharNumber < 0 ) || ( sCharNumber >= MAX_CHARACTER_COUNT ) ) + { + return( FALSE ); + } + + // is the character a valid one? + if( gCharactersList[ sCharNumber ].fValid == FALSE ) + { + return ( FALSE ); + } + + // if the highlighted line character is also selected + if ( ( giSleepHighLine != -1 ) && IsEntryInSelectedListSet ( ( INT8 ) giSleepHighLine ) ) + { + // then ALL selected lines will be affected + if( IsEntryInSelectedListSet( ( INT8 ) sCharNumber ) ) + { + return( TRUE ); + } + } + else + { + // ONLY the highlighted line will be affected + if ( sCharNumber == giSleepHighLine ) + { + return( TRUE ); + } + } + + return( FALSE ); +} + +void DisableTeamInfoPanels( void ) +{ + // disable team info panel + fDisableDueToBattleRoster = TRUE; + + return; +} + + +void EnableTeamInfoPanels( void ) +{ + // enable team info panel + fDisableDueToBattleRoster = FALSE; + + return; +} + + +/* +void ActivateSoldierPopup( SOLDIERTYPE *pSoldier, UINT8 ubPopupType, INT16 xp, INT16 yp ) +{ + // will activate the pop up for prebattle interface + + // get the soldier id number + INT8 bCounter = 0; + INT8 bCharacter = -1; + + + for( bCounter = 0; bCounter < MAX_CHARACTER_COUNT; bCounter++ ) + { + if( gCharactersList[ bCounter ].fValid == TRUE ) + { + // is this guy the passed soldier? + if( pSoldier == &( Menptr[ gCharactersList[ bCounter ].usSolID ] ) ) + { + bCharacter = bCounter; + break; + } + } + } + + giBoxY = ( INT32 ) yp; + // which type of box do we show? + switch( ubPopupType ) + { + case( ASSIGNMENT_POPUP ): + bSelectedDestChar = -1; + bSelectedContractChar = -1; + bSelectedAssignChar = bCharacter; + if( ( pSoldier->bLife > 0 ) &&( pSoldier->bAssignment != ASSIGNMENT_POW ) ) + { + fShowAssignmentMenu = TRUE; + } + else + { + fShowRemoveMenu = TRUE; + } + + // set box y positions + AssignmentPosition.iY = giBoxY; + TrainPosition.iY = AssignmentPosition.iY + GetFontHeight( MAP_SCREEN_FONT )* ASSIGN_MENU_TRAIN; + AttributePosition.iY = TrainPosition.iY; + SquadPosition.iY = AssignmentPosition.iY; + break; + case( DESTINATION_POPUP ): + bSelectedDestChar = bCharacter; + bSelectedContractChar = -1; + bSelectedAssignChar = -1; + + // set box y value + ContractPosition.iY = giBoxY; + break; + case( CONTRACT_POPUP ): + bSelectedDestChar = -1; + bSelectedContractChar = bCharacter; + bSelectedAssignChar = -1; + RebuildContractBoxForMerc( pSoldier ); + + if( ( pSoldier->bLife > 0 ) &&( pSoldier->bAssignment != ASSIGNMENT_POW ) ) + { + fShowContractMenu = TRUE; + } + else + { + fShowRemoveMenu = TRUE; + } + break; + } +} +*/ + + + +INT32 DoMapMessageBoxWithRect( UINT8 ubStyle, INT16 *zString, UINT32 uiExitScreen, UINT16 usFlags, MSGBOX_CALLBACK ReturnCallback, SGPRect *pCenteringRect ) +{ // reset the highlighted line + giHighLine = -1; + return DoMessageBox( ubStyle, zString, uiExitScreen, ( UINT16 ) ( usFlags | MSG_BOX_FLAG_USE_CENTERING_RECT ), ReturnCallback, pCenteringRect ); +} + + +INT32 DoMapMessageBox( UINT8 ubStyle, INT16 * zString, UINT32 uiExitScreen, UINT16 usFlags, MSGBOX_CALLBACK ReturnCallback ) +{ + // WANNE 2 + SGPRect CenteringRect= {0, 0, SCREEN_WIDTH, INV_INTERFACE_START_Y }; + + // reset the highlighted line + giHighLine = -1; + + // do message box and return + return DoMessageBox( ubStyle, zString, uiExitScreen, ( UINT16 ) ( usFlags| MSG_BOX_FLAG_USE_CENTERING_RECT ), ReturnCallback, &CenteringRect ); +} + + + +void GoDownOneLevelInMap( void ) +{ + JumpToLevel( iCurrentMapSectorZ + 1 ); +} + + +void GoUpOneLevelInMap( void ) +{ + JumpToLevel( iCurrentMapSectorZ - 1 ); +} + + +void JumpToLevel( INT32 iLevel ) +{ + if( IsMapScreenHelpTextUp() ) + { + // stop mapscreen text + StopMapScreenHelpText( ); + return; + } + + if( gfPreBattleInterfaceActive == TRUE ) + { + return; + } + + // disable level-changes while in inventory pool (for keyboard equivalents!) + if( fShowMapInventoryPool ) + return; + + + if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + { + AbortMovementPlottingMode( ); + } + + if( iLevel < 0 ) + { + iLevel = 0; + } + + if( iLevel > MAX_DEPTH_OF_MAP ) + { + iLevel = MAX_DEPTH_OF_MAP; + } + + // set current sector Z to level passed + ChangeSelectedMapSector( sSelMapX, sSelMapY, ( INT8 )iLevel ); +} + + +// check against old contract times, update as nessacary +void CheckAndUpdateBasedOnContractTimes( void ) +{ + INT32 iCounter = 0; + INT32 iTimeRemaining = 0; + + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + if( gCharactersList[iCounter].fValid == TRUE ) + { + // what kind of merc + if(Menptr[gCharactersList[iCounter].usSolID].ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC) + { + // amount of time left on contract + iTimeRemaining=Menptr[gCharactersList[iCounter].usSolID].iEndofContractTime-GetWorldTotalMin(); + if(iTimeRemaining >60*24) + { + // more than a day, display in green + iTimeRemaining/=(60*24); + + // check if real change in contract time + if( iTimeRemaining != iOldContractTimes[ iCounter ]) + { + iOldContractTimes[ iCounter ] = iTimeRemaining; + + // dirty screen + fTeamPanelDirty = TRUE; + fCharacterInfoPanelDirty = TRUE; + } + } + else + { + // less than a day, display hours left in red + iTimeRemaining/=60; + + // check if real change in contract time + if( iTimeRemaining != iOldContractTimes[ iCounter ]) + { + iOldContractTimes[ iCounter ] = iTimeRemaining; + // dirty screen + fTeamPanelDirty = TRUE; + fCharacterInfoPanelDirty = TRUE; + } + } + } + else if( Menptr[gCharactersList[iCounter].usSolID].ubWhatKindOfMercAmI == MERC_TYPE__MERC ) + { + iTimeRemaining = Menptr[gCharactersList[iCounter].usSolID].iTotalContractLength; + + if( iTimeRemaining != iOldContractTimes[ iCounter ]) + { + iOldContractTimes[ iCounter ] = iTimeRemaining; + + // dirty screen + fTeamPanelDirty = TRUE; + fCharacterInfoPanelDirty = TRUE; + } + } + } + } +} + + + +void HandleDisplayOfSelectedMercArrows( void ) +{ + INT16 sYPosition = 0; + HVOBJECT hHandle; + UINT8 ubCount = 0; + INT16 usVehicleCount = 0; + + // blit an arrow by the name of each merc in a selected list + if( bSelectedInfoChar == -1 ) + { + return; + } + + // is the character valid? + if( gCharactersList[ bSelectedInfoChar ].fValid == FALSE ) + { + return; + } + + if( fShowInventoryFlag == TRUE ) + { + return; + } + // now blit one by the selected merc + sYPosition = Y_START+( bSelectedInfoChar * ( Y_SIZE + 2 ) ) - 1; + + + if( bSelectedInfoChar >= FIRST_VEHICLE ) + { + // WANNE 2 + usVehicleCount = bSelectedInfoChar - FIRST_VEHICLE; + sYPosition = usVehicleY+( usVehicleCount * ( Y_SIZE + 2) ) - 1;; + } + + + GetVideoObject( &hHandle, guiSelectedCharArrow ); + BltVideoObject( guiSAVEBUFFER , hHandle, 0,SELECTED_CHAR_ARROW_X, sYPosition , VO_BLT_SRCTRANSPARENCY,NULL ); + + // now run through the selected list of guys, an arrow for each + for( ubCount = 0; ubCount < MAX_CHARACTER_COUNT; ubCount++ ) + { + if( gCharactersList[ ubCount ].fValid == TRUE ) + { + + // are they in the selected list or int he same mvt group as this guy + if( ( IsEntryInSelectedListSet( ubCount ) == TRUE ) || ( ( bSelectedDestChar != - 1 ) ? ( ( Menptr[ gCharactersList[ ubCount ].usSolID ].ubGroupID != 0 ) ? ( Menptr[ gCharactersList[ bSelectedDestChar ].usSolID ].ubGroupID == Menptr[ gCharactersList[ ubCount ].usSolID ].ubGroupID ) : FALSE ) : FALSE ) ) + { + sYPosition = Y_START+( ubCount * ( Y_SIZE + 2) ) - 1; + + if( ubCount >= FIRST_VEHICLE ) + { + // WANNE 2 + usVehicleCount = ubCount - FIRST_VEHICLE; + sYPosition = usVehicleY+( usVehicleCount * ( Y_SIZE + 2) ) - 1;; + } + + GetVideoObject( &hHandle, guiSelectedCharArrow ); + BltVideoObject( guiSAVEBUFFER , hHandle, 0,SELECTED_CHAR_ARROW_X, sYPosition , VO_BLT_SRCTRANSPARENCY,NULL ); + } + } + } + return; +} + + + +void HandleDisplayOfItemPopUpForSector( INT16 sMapX, INT16 sMapY, INT16 sMapZ ) +{ + // handle display of item pop up for this sector + // check if anyone alive in this sector + ITEM_POOL *pItemPool = NULL; + static BOOLEAN fWasInited = FALSE; + + if( bSelectedInfoChar == -1 ) + { + return; + } + + + if( ( fWasInited == FALSE ) && ( fMapInventoryPoolInited ) ) + { + if( gCharactersList[ bSelectedInfoChar ].fValid == TRUE ) + { + if( ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID].sSectorX == sMapX ) && ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID].sSectorY == sMapY ) && ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID].bSectorZ == sMapZ ) && ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID].bActive ) && ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID].bLife >= OKLIFE ) ) + { + // valid character + InitializeItemPickupMenu( &( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID] ), NOWHERE , pItemPool, MAP_INVEN_POOL_X, MAP_INVEN_POOL_Y, -1 ); + fWasInited = TRUE; + + CreateScreenMaskForInventoryPoolPopUp( ); + } + } + } + else if( ( fWasInited == TRUE ) && ( fMapInventoryPoolInited == FALSE ) ) + { + fWasInited = FALSE; + + // now clear up the box + RemoveItemPickupMenu( ); + + // remove screen mask + RemoveScreenMaskForInventoryPoolPopUp( ); + + // drity nessacary regions + fMapPanelDirty = TRUE; + + } + + // showing it + if( ( fMapInventoryPoolInited ) && ( fWasInited ) ) + { + SetPickUpMenuDirtyLevel( DIRTYLEVEL2 ); + RenderItemPickupMenu( ); + } + + + return; +} + + + +void CreateScreenMaskForInventoryPoolPopUp( void ) +{ + // a screen mask for the inventory pop up + MSYS_DefineRegion( &gInventoryScreenMask, 0, 0 , SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGH - 1, + MSYS_NO_CURSOR, MSYS_NO_CALLBACK, InventoryScreenMaskBtnCallback ); + +} + +void RemoveScreenMaskForInventoryPoolPopUp( void ) +{ + // remove screen mask + MSYS_RemoveRegion( &gInventoryScreenMask ); +} + + +// invnetory screen mask btn callback +void InventoryScreenMaskBtnCallback(MOUSE_REGION * pRegion, INT32 iReason ) +{ + // inventory screen mask btn callback + if(iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) + { + fMapInventoryPoolInited = FALSE; + } +} + +void GetMoraleString( SOLDIERTYPE *pSoldier, STR16 sString ) +{ + INT8 bMorale = pSoldier->bMorale; + + if ( pSoldier->uiStatusFlags & SOLDIER_DEAD ) + { + wcscpy( sString, pMoralStrings[ 5 ] ); + } + else if( bMorale > 80 ) + { + wcscpy( sString, pMoralStrings[ 0 ] ); + } + else if( bMorale > 65 ) + { + wcscpy( sString, pMoralStrings[ 1 ] ); + } + else if( bMorale > 35 ) + { + wcscpy( sString, pMoralStrings[ 2 ] ); + } + else if( bMorale > 20 ) + { + wcscpy( sString, pMoralStrings[ 3 ] ); + } + else + { + wcscpy( sString, pMoralStrings[ 4 ] ); + } +} + + + +// NOTE: This doesn't use the "LeaveList" system at all! +void HandleLeavingOfEquipmentInCurrentSector( UINT32 uiMercId ) +{ + // just drop the stuff in the current sector + INT32 iCounter = 0; + INT16 sGridNo, sTempGridNo; + + if( Menptr[ uiMercId ].sSectorX != gWorldSectorX || Menptr[ uiMercId ].sSectorY != gWorldSectorY || Menptr[ uiMercId ].bSectorZ != gbWorldSectorZ ) + { + // ATE: Use insertion gridno if not nowhere and insertion is gridno + if ( Menptr[ uiMercId ].ubStrategicInsertionCode == INSERTION_CODE_GRIDNO && Menptr[ uiMercId ].usStrategicInsertionData != NOWHERE ) + { + sGridNo = Menptr[ uiMercId ].usStrategicInsertionData; + } + else + { + // Set flag for item... + sGridNo = RandomGridNo(); + } + } + else + { + // ATE: Mercs can have a gridno of NOWHERE..... + sGridNo = Menptr[ uiMercId ].sGridNo; + + if ( sGridNo == NOWHERE ) + { + sGridNo = RandomGridNo(); + + sTempGridNo = FindNearestAvailableGridNoForItem( sGridNo, 5 ); + if( sTempGridNo == NOWHERE ) + sTempGridNo = FindNearestAvailableGridNoForItem( sGridNo, 15 ); + + if ( sTempGridNo != NOWHERE ) + { + sGridNo = sTempGridNo; + } + } + } + + for( iCounter = 0; iCounter < NUM_INV_SLOTS; iCounter++ ) + { + // slot found, + // check if actual item + if( Menptr[ uiMercId ].inv[ iCounter ].ubNumberOfObjects > 0 ) + { + if( Menptr[ uiMercId ].sSectorX != gWorldSectorX || Menptr[ uiMercId ].sSectorY != gWorldSectorY || Menptr[ uiMercId ].bSectorZ != gbWorldSectorZ ) + { + // Set flag for item... + AddItemsToUnLoadedSector( Menptr[ uiMercId ].sSectorX, Menptr[ uiMercId ].sSectorY, Menptr[ uiMercId ].bSectorZ , sGridNo, 1, &( Menptr[ uiMercId ].inv[ iCounter ]) , Menptr[ uiMercId ].bLevel, WOLRD_ITEM_FIND_SWEETSPOT_FROM_GRIDNO | WORLD_ITEM_REACHABLE, 0, 1, FALSE ); + } + else + { + AddItemToPool( sGridNo, &( Menptr[ uiMercId ].inv[ iCounter ] ) , 1, Menptr[ uiMercId ].bLevel, WORLD_ITEM_REACHABLE, 0 ); + } + } + } + + DropKeysInKeyRing( MercPtrs[ uiMercId ], sGridNo, MercPtrs[ uiMercId ]->bLevel, 1, FALSE, 0, FALSE ); + +} + + + +void HandleMercLeavingEquipmentInOmerta( UINT32 uiMercId ) +{ + INT32 iSlotIndex = 0; + + // stash the items into a linked list hanging of a free "leave item list" slot + if( ( iSlotIndex = SetUpDropItemListForMerc( uiMercId ) ) != -1 ) + { + // post event to drop it there 6 hours later + AddStrategicEvent( EVENT_MERC_LEAVE_EQUIP_IN_OMERTA, GetWorldTotalMin() + ( 6 * 60 ), iSlotIndex ); + } + else + { + // otherwise there's no free slots left (shouldn't ever happen) + AssertMsg( FALSE, "HandleMercLeavingEquipmentInOmerta: No more free slots, equipment lost" ); + } +} + + +void HandleMercLeavingEquipmentInDrassen( UINT32 uiMercId ) +{ + INT32 iSlotIndex = 0; + + // stash the items into a linked list hanging of a free "leave item list" slot + if( ( iSlotIndex = SetUpDropItemListForMerc( uiMercId ) ) != -1 ) + { + // post event to drop it there 6 hours later + AddStrategicEvent( EVENT_MERC_LEAVE_EQUIP_IN_DRASSEN, GetWorldTotalMin() + ( 6 * 60 ), iSlotIndex ); + } + else + { + // otherwise there's no free slots left (shouldn't ever happen) + AssertMsg( FALSE, "HandleMercLeavingEquipmentInDrassen: No more free slots, equipment lost" ); + } +} + + +void HandleEquipmentLeftInOmerta( UINT32 uiSlotIndex ) +{ + MERC_LEAVE_ITEM *pItem; + CHAR16 sString[ 128 ]; + + + Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS ); + + pItem = gpLeaveListHead[ uiSlotIndex ]; + + if( pItem ) + { + if ( guiLeaveListOwnerProfileId[ uiSlotIndex ] != NO_PROFILE ) + { + swprintf( sString, pLeftEquipmentString[ 0 ], gMercProfiles[ guiLeaveListOwnerProfileId[ uiSlotIndex ] ].zNickname ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, sString); + } + else + { + swprintf( sString, L"A departing merc has left their equipment in Omerta." ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, sString); + } + } + + while( pItem ) + { + if( gWorldSectorX != OMERTA_LEAVE_EQUIP_SECTOR_X || gWorldSectorY != OMERTA_LEAVE_EQUIP_SECTOR_Y || gbWorldSectorZ != OMERTA_LEAVE_EQUIP_SECTOR_Z ) + { + // given this slot value, add to sector item list + AddItemsToUnLoadedSector( OMERTA_LEAVE_EQUIP_SECTOR_X, OMERTA_LEAVE_EQUIP_SECTOR_Y, OMERTA_LEAVE_EQUIP_SECTOR_Z, OMERTA_LEAVE_EQUIP_GRIDNO, 1, &( pItem -> o ) , 0, WORLD_ITEM_REACHABLE, 0, 1, FALSE ); + } + else + { + AddItemToPool( OMERTA_LEAVE_EQUIP_GRIDNO, &( pItem->o ), 1, 0, WORLD_ITEM_REACHABLE, 0 ); + } + pItem = pItem -> pNext; + } + + FreeLeaveListSlot( uiSlotIndex ); +} + + + +void HandleEquipmentLeftInDrassen( UINT32 uiSlotIndex ) +{ + MERC_LEAVE_ITEM *pItem; + CHAR16 sString[ 128 ]; + + + Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS ); + + pItem = gpLeaveListHead[ uiSlotIndex ]; + + if( pItem ) + { + if ( guiLeaveListOwnerProfileId[ uiSlotIndex ] != NO_PROFILE ) + { + swprintf( sString, pLeftEquipmentString[ 1 ], gMercProfiles[ guiLeaveListOwnerProfileId[ uiSlotIndex ] ].zNickname ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, sString); + } + else + { + swprintf( sString, L"A departing merc has left their equipment in Drassen." ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, sString); + } + } + + while( pItem ) + { + if( gWorldSectorX != BOBBYR_SHIPPING_DEST_SECTOR_X || gWorldSectorY != BOBBYR_SHIPPING_DEST_SECTOR_Y || gbWorldSectorZ != BOBBYR_SHIPPING_DEST_SECTOR_Z ) + { + // given this slot value, add to sector item list + AddItemsToUnLoadedSector( BOBBYR_SHIPPING_DEST_SECTOR_X, BOBBYR_SHIPPING_DEST_SECTOR_Y, BOBBYR_SHIPPING_DEST_SECTOR_Z, 10433, 1, &( pItem -> o ) , 0, WORLD_ITEM_REACHABLE, 0, 1, FALSE ); + } + else + { + AddItemToPool( 10433, &( pItem->o ), 1, 0, WORLD_ITEM_REACHABLE, 0 ); + } + pItem = pItem->pNext; + } + + FreeLeaveListSlot( uiSlotIndex ); +} + + +void InitLeaveList( void ) +{ + INT32 iCounter = 0; + + // init leave list with NULLS/zeroes + for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ ) + { + gpLeaveListHead[ iCounter ] = NULL; + guiLeaveListOwnerProfileId[ iCounter ] = NO_PROFILE; + } +} + + +void ShutDownLeaveList( void ) +{ + INT32 iCounter = 0; + + for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ ) + { + // go through nodes and free them + if ( gpLeaveListHead[ iCounter ] != NULL ) + { + FreeLeaveListSlot( iCounter ); + } + } +} + + +BOOLEAN AddItemToLeaveIndex( OBJECTTYPE *o, UINT32 uiSlotIndex ) +{ + MERC_LEAVE_ITEM *pItem, *pCurrentItem; + + Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS ); + + + if( o == NULL ) + { + return( FALSE ); + } + + // allocate space + pItem = (MERC_LEAVE_ITEM *) MemAlloc( sizeof( MERC_LEAVE_ITEM ) ); + + // copy object + memcpy( &( pItem->o ), o, sizeof( OBJECTTYPE ) ); + + // nobody afterwards + pItem->pNext = NULL; + + // now add to list in this index slot + pCurrentItem = gpLeaveListHead[ uiSlotIndex ]; + + if( pCurrentItem == NULL ) + { + gpLeaveListHead[ uiSlotIndex ] = pItem; + return( TRUE ); + } + + // move through list + while( pCurrentItem ->pNext ) + { + pCurrentItem = pCurrentItem->pNext; + } + + // found + pCurrentItem->pNext = pItem; + + return( TRUE ); +} + + +// release memory for all items in this slot's leave item list +void FreeLeaveListSlot( UINT32 uiSlotIndex ) +{ + MERC_LEAVE_ITEM *pCurrent = NULL, *pTemp = NULL; + + Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS ); + + pCurrent = gpLeaveListHead[ uiSlotIndex ]; + + // go through nodes and free them + while( pCurrent ) + { + pTemp = pCurrent->pNext; + MemFree( pCurrent ); + pCurrent = pTemp; + } + + gpLeaveListHead[ uiSlotIndex ] = NULL; +} + + + +INT32 FindFreeSlotInLeaveList( void ) +{ + INT32 iCounter = 0; + + for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ ) + { + if( gpLeaveListHead[ iCounter ] == NULL ) + { + return( iCounter ); + } + } + + return( -1 ); +} + + +INT32 SetUpDropItemListForMerc( UINT32 uiMercId ) +{ + // will set up a drop list for this grunt, remove items from inventory, and profile + INT32 iSlotIndex = -1; + INT32 iCounter = 0; + + iSlotIndex = FindFreeSlotInLeaveList( ); + if( iSlotIndex == -1 ) + { + return( -1 ); + } + + for( iCounter = 0; iCounter < NUM_INV_SLOTS; iCounter++ ) + { + // slot found, + // check if actual item + if( Menptr[ uiMercId ].inv[ iCounter ].ubNumberOfObjects > 0 ) + { + // make a linked list of the items left behind, with the ptr to its head in this free slot + AddItemToLeaveIndex( &( Menptr[ uiMercId ].inv[ iCounter ] ), iSlotIndex ); + + // store owner's profile id for the items added to this leave slot index + SetUpMercAboutToLeaveEquipment( Menptr[ uiMercId ].ubProfile, iSlotIndex ); + } + } + + // ATE: Added this to drop keyring keys - the 2nd last paramter says to add it to a leave list... + // the gridno, level and visiblity are ignored + DropKeysInKeyRing( MercPtrs[ uiMercId ], NOWHERE, 0, 0, TRUE, iSlotIndex, FALSE ); + + // zero out profiles + memset( ( gMercProfiles[ Menptr[ uiMercId ].ubProfile ].bInvStatus ), 0, sizeof( UINT8 ) * 19 ); + memset( ( gMercProfiles[ Menptr[ uiMercId ].ubProfile ].bInvNumber ), 0, sizeof( UINT8 ) * 19 ); + memset( ( gMercProfiles[ Menptr[ uiMercId ].ubProfile ].inv ), 0, sizeof( UINT16 ) * 19 ); + + return( iSlotIndex ); +} + + +// store owner's profile id for the items added to this leave slot index +void SetUpMercAboutToLeaveEquipment( UINT32 ubProfileId, UINT32 uiSlotIndex ) +{ + Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS ); + + // store the profile ID of this merc in the same slot that the items are gonna be dropped in + guiLeaveListOwnerProfileId[ uiSlotIndex ] = ubProfileId; + +} + + +/* +BOOLEAN RemoveItemFromLeaveIndex( MERC_LEAVE_ITEM *pItem, UINT32 uiSlotIndex ) +{ + MERC_LEAVE_ITEM *pCurrentItem = NULL; + + Assert( uiSlotIndex < NUM_LEAVE_LIST_SLOTS ); + + if( pItem == NULL ) + { + return( FALSE ); + } + + // item is head of list? +//ARM: THIS DOESN'T MAKE SENSE, pCurrentItem is always NULL at this stage! + if( pItem == pCurrentItem ) + { + gpLeaveListHead[ uiSlotIndex ] = pCurrentItem ->pNext; + MemFree( pItem ); + pItem = NULL; + return( TRUE ); + } + + // in the body + while( ( pCurrentItem->pNext != pItem ) && ( pCurrentItem -> pNext != NULL ) ) + { + pCurrentItem = pCurrentItem -> pNext; + } + + // item not found + if( pCurrentItem->pNext == NULL ) + { + return( FALSE ); + } + + // set to next after next + pCurrentItem->pNext = pCurrentItem->pNext->pNext; + + // free space and null ptr + MemFree( pItem ); + pItem = NULL; + + return( TRUE ); +} +*/ + + + +void HandleGroupAboutToArrive( void ) +{ + // reblit map to change the color of the "people in motion" marker + fMapPanelDirty = TRUE; + + // ARM - commented out - don't see why this is needed +// fTeamPanelDirty = TRUE; +// fCharacterInfoPanelDirty = TRUE; + + return; +} + + +/* +void HandleMapScreenUpArrow( void ) +{ + INT32 iValue = 0; + INT32 iHighLine = 0; + + // check state and update + if( fShowAssignmentMenu == TRUE ) + { + if( GetBoxShadeFlag( ghAssignmentBox, iValue ) == FALSE ) + { + if( iHighLine == 0) + { + iHighLine = ( INT32 )GetNumberOfLinesOfTextInBox( ghAssignmentBox ); + } + else + { + iHighLine++; + } + } + } + else + { + if( ( giHighLine == 0 ) || ( giHighLine == -1 ) ) + { + giHighLine = GetNumberOfCharactersOnPlayersTeam( ) - 1; + fTeamPanelDirty = TRUE; + } + else + { + giHighLine--; + fTeamPanelDirty = TRUE; + } + + } +} + + +void HandleMapScreenDownArrow( void ) +{ + INT32 iValue = 0; + INT32 iHighLine = 0; + + // check state and update + if( fShowContractMenu == TRUE ) + { + if( iHighLine == ( INT32 )GetNumberOfLinesOfTextInBox( ghContractBox ) - 1 ) + { + iHighLine = 0; + } + else + { + iHighLine++; + } + + HighLightBoxLine( ghContractBox, iHighLine ); + } + else if( fShowAssignmentMenu == TRUE ) + { + if( GetBoxShadeFlag( ghAssignmentBox, iValue ) == FALSE ) + { + if( iHighLine == ( INT32 )GetNumberOfLinesOfTextInBox( ghAssignmentBox ) - 1 ) + { + iHighLine = 0; + } + else + { + iHighLine--; + } + } + } + else + { + if( ( giHighLine == GetNumberOfCharactersOnPlayersTeam( ) - 1 ) || ( giHighLine == -1 ) ) + { + giHighLine = 0; + fTeamPanelDirty = TRUE; + } + else + { + giHighLine++; + fTeamPanelDirty = TRUE; + } + + } +} + + +INT32 GetNumberOfCharactersOnPlayersTeam( void ) +{ + INT32 iNumberOfPeople = 0, iCounter = 0; + + for(iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + if( gCharactersList[ iCounter ].fValid == TRUE ) + { + iNumberOfPeople++; + } + } + + return( iNumberOfPeople ); +} +*/ + + +void CreateMapStatusBarsRegion( void ) +{ + + // create the status region over the bSelectedCharacter info region, to get quick rundown of merc's status + MSYS_DefineRegion( &gMapStatusBarsRegion, BAR_INFO_X - 3, BAR_INFO_Y - 42,(INT16)( BAR_INFO_X + 17), (INT16)(BAR_INFO_Y ), MSYS_PRIORITY_HIGH + 5, + MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK ); + + return; +} + + +void RemoveMapStatusBarsRegion( void ) +{ + + // remove the bSelectedInfoCharacter helath, breath and morale bars info region + MSYS_RemoveRegion( &gMapStatusBarsRegion ); + + return; +} + +void UpdateCharRegionHelpText( void ) +{ + CHAR16 sString[ 128 ]; + CHAR16 pMoraleStr[ 128 ]; + SOLDIERTYPE *pSoldier = NULL; + + + if( ( bSelectedInfoChar != -1 ) && ( gCharactersList[ bSelectedInfoChar ].fValid == TRUE ) ) + { + // valid soldier selected + pSoldier = MercPtrs[ gCharactersList[ bSelectedInfoChar ].usSolID ]; + + // health/energy/morale + if( pSoldier->bAssignment != ASSIGNMENT_POW ) + { + if ( pSoldier->bLife != 0 ) + { + if ( AM_A_ROBOT( MercPtrs[ gCharactersList[ bSelectedInfoChar ].usSolID ] ) ) + { + // robot (condition only) + swprintf( sString, L"%s: %d/%d", + pMapScreenStatusStrings[ 3 ], pSoldier->bLife, pSoldier->bLifeMax ); + } + else if ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ].uiStatusFlags & SOLDIER_VEHICLE ) + { + // vehicle (condition/fuel) + swprintf( sString, L"%s: %d/%d, %s: %d/%d", + pMapScreenStatusStrings[ 3 ], pSoldier->bLife, pSoldier->bLifeMax, + pMapScreenStatusStrings[ 4 ], pSoldier->bBreath, pSoldier->bBreathMax ); + } + else + { + // person (health/energy/morale) + GetMoraleString( pSoldier, pMoraleStr ); + swprintf( sString, L"%s: %d/%d, %s: %d/%d, %s: %s", + pMapScreenStatusStrings[ 0 ], pSoldier->bLife, pSoldier->bLifeMax, + pMapScreenStatusStrings[ 1 ], pSoldier->bBreath, pSoldier->bBreathMax, + pMapScreenStatusStrings[ 2 ], pMoraleStr ); + } + } + else + { + wcscpy( sString, L"" ); + } + } + else + { + // POW - stats unknown + swprintf( sString, L"%s: ??, %s: ??, %s: ??", pMapScreenStatusStrings[ 0 ], pMapScreenStatusStrings[ 1 ], pMapScreenStatusStrings[ 2 ] ); + } + + SetRegionFastHelpText( &gMapStatusBarsRegion, sString ); + + + // update CONTRACT button help text + if ( CanExtendContractForCharSlot( bSelectedInfoChar ) ) + { + SetButtonFastHelpText( giMapContractButton, pMapScreenMouseRegionHelpText[ 3 ] ); + EnableButton( giMapContractButton ); + } + else + { + SetButtonFastHelpText( giMapContractButton, L"" ); + DisableButton( giMapContractButton ); + } + + + if ( CanToggleSelectedCharInventory( ) ) + { + // inventory + if( fShowInventoryFlag ) + { + SetRegionFastHelpText( &gCharInfoHandRegion, pMiscMapScreenMouseRegionHelpText[ 2 ] ); + } + else + { + SetRegionFastHelpText( &gCharInfoHandRegion, pMiscMapScreenMouseRegionHelpText[ 0 ] ); + } + } + else // can't toggle it, don't show any inventory help text + { + SetRegionFastHelpText( &gCharInfoHandRegion, L"" ); + } + } + else + { + // invalid soldier + SetRegionFastHelpText( &(gMapStatusBarsRegion), L"" ); + SetButtonFastHelpText( giMapContractButton, L"" ); + SetRegionFastHelpText( &gCharInfoHandRegion, L"" ); + DisableButton( giMapContractButton ); + } +} + + +// find this merc in the mapscreen list and set as selected +void FindAndSetThisContractSoldier( SOLDIERTYPE *pSoldier ) +{ + INT32 iCounter = 0; + + fShowContractMenu = FALSE; + + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + if( gCharactersList[ iCounter].fValid == TRUE ) + { + if( gCharactersList[ iCounter].usSolID == pSoldier->ubID ) + { + ChangeSelectedInfoChar( ( INT8 )iCounter, TRUE ); + bSelectedContractChar = ( INT8 )iCounter; + fShowContractMenu = TRUE; + + // create + RebuildContractBoxForMerc( pSoldier ); + + fTeamPanelDirty = TRUE; + fCharacterInfoPanelDirty = TRUE; + } + } + } +} + + +void HandleMAPUILoseCursorFromOtherScreen( void ) +{ + // rerender map without cursors + fMapPanelDirty = TRUE; + + if ( fInMapMode ) + { + RenderMapRegionBackground( ); + } + return; +} + + +void UpdateMapScreenAssignmentPositions( void ) +{ + // set the position of the pop up boxes + SGPPoint pPoint; + + + if( guiCurrentScreen != MAP_SCREEN ) + { + return; + } + + + if( bSelectedAssignChar == -1 ) + { + if( gfPreBattleInterfaceActive == FALSE ) + { + giBoxY = 0; + } + return; + } + + if( gCharactersList[ bSelectedAssignChar ].fValid == FALSE ) + { + if( gfPreBattleInterfaceActive == FALSE ) + { + giBoxY = 0; + } + return; + } + + if( gfPreBattleInterfaceActive ) + { + // do nothing + } + else + { + giBoxY = ( Y_START + ( bSelectedAssignChar ) * ( Y_SIZE + 2 ) ); + +/* ARM: Removed this - refreshes fine without it, apparently + // make sure the menus don't overlap the map screen bottom panel (but where did 102 come from?) + if( giBoxY >= ( MAP_BOTTOM_Y - 102 ) ) + giBoxY = MAP_BOTTOM_Y - 102; +*/ + } + + + + AssignmentPosition.iY = giBoxY; + + AttributePosition.iY = TrainPosition.iY = AssignmentPosition.iY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 )* ASSIGN_MENU_TRAIN; + + VehiclePosition.iY = AssignmentPosition.iY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_VEHICLE; + SquadPosition.iY = AssignmentPosition.iY; + + if( fShowAssignmentMenu ) + { + GetBoxPosition( ghAssignmentBox, &pPoint); + pPoint.iY = giBoxY; + + SetBoxPosition( ghAssignmentBox, pPoint ); + + GetBoxPosition( ghEpcBox, &pPoint); + pPoint.iY = giBoxY; + + SetBoxPosition( ghEpcBox, pPoint ); + } + + if( fShowAttributeMenu ) + { + GetBoxPosition( ghAttributeBox, &pPoint); + + pPoint.iY = giBoxY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_TRAIN; + + SetBoxPosition( ghAttributeBox, pPoint ); + } + + if( fShowRepairMenu ) + { + GetBoxPosition( ghRepairBox, &pPoint); + pPoint.iY = giBoxY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_REPAIR; + + SetBoxPosition( ghRepairBox, pPoint ); + } + + + + return; +} + + + +void RandomMercInGroupSaysQuote( GROUP *pGroup, UINT16 usQuoteNum ) +{ + PLAYERGROUP *pPlayer; + SOLDIERTYPE *pSoldier; + UINT8 ubMercsInGroup[ 20 ]; + UINT8 ubNumMercs = 0; + UINT8 ubChosenMerc; + + + // if traversing tactically, don't do this, unless time compression was required for some reason (don't go to sector) + if ( ( gfTacticalTraversal || ( pGroup->ubSectorZ > 0 ) ) && !IsTimeBeingCompressed() ) + { + return; + } + + + // Let's choose somebody in group..... + pPlayer = pGroup->pPlayerList; + + while( pPlayer != NULL ) + { + pSoldier = pPlayer->pSoldier; + Assert( pSoldier ); + + if ( pSoldier->bLife >= OKLIFE && !( pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) && + !AM_A_ROBOT( pSoldier ) && !AM_AN_EPC( pSoldier ) && !pSoldier->fMercAsleep ) + { + ubMercsInGroup[ ubNumMercs ] = pSoldier->ubID; + ubNumMercs++; + } + + pPlayer = pPlayer->next; + } + + // At least say quote.... + if ( ubNumMercs > 0 ) + { + ubChosenMerc = (UINT8)Random( ubNumMercs ); + pSoldier = MercPtrs[ ubMercsInGroup[ ubChosenMerc ] ]; + + TacticalCharacterDialogue( pSoldier, usQuoteNum ); + } +} + + +INT32 GetNumberOfPeopleInCharacterList( void ) +{ + INT32 iCounter = 0, iCount = 0; + + // get the number of valid mercs in the mapscreen character list + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + if( gCharactersList[ iCounter].fValid == TRUE ) + { + // another valid character + iCount++; + } + } + + return( iCount ); +} + + + +BOOLEAN ValidSelectableCharForNextOrPrev( INT32 iNewCharSlot ) +{ + BOOLEAN fHoldingItem = FALSE; + + // if holding an item + if ( ( gMPanelRegion.Cursor == EXTERN_CURSOR ) || gpItemPointer || fMapInventoryItem ) + { + fHoldingItem = TRUE; + } + + + // if showing merc inventory, or holding an item + if ( fShowInventoryFlag || fHoldingItem ) + { + // the new guy must have accessible inventory + if ( !MapCharacterHasAccessibleInventory( ( INT8 ) iNewCharSlot ) ) + { + return( FALSE ); + } + } + + + if ( fHoldingItem ) + { + return ( MapscreenCanPassItemToCharNum( iNewCharSlot ) ); + } + else + { + return( TRUE ); + } +} + + + +BOOLEAN MapscreenCanPassItemToCharNum( INT32 iNewCharSlot ) +{ + SOLDIERTYPE *pNewSoldier; + SOLDIERTYPE *pOldSoldier; + + + // assumes we're holding an item + Assert( ( gMPanelRegion.Cursor == EXTERN_CURSOR ) || gpItemPointer || fMapInventoryItem ); + + + // if in a hostile sector, disallow + if ( gTacticalStatus.fEnemyInSector ) + { + return( FALSE ); + } + + // can't pass items to nobody! + if ( iNewCharSlot == -1 ) + { + return( FALSE ); + } + + + pNewSoldier = MercPtrs[ gCharactersList[ iNewCharSlot ].usSolID ]; + + + // if showing sector inventory, and the item came from there + if ( fShowMapInventoryPool && !gpItemPointerSoldier && fMapInventoryItem ) + { + // disallow passing items to anyone not in that sector + if ( pNewSoldier->sSectorX != sSelMapX || + pNewSoldier->sSectorY != sSelMapY || + pNewSoldier->bSectorZ != ( INT8 )( iCurrentMapSectorZ ) ) + { + return( FALSE ); + } + + if ( pNewSoldier->fBetweenSectors ) + { + return( FALSE ); + } + } + + + // if we know who it came from + if ( gpItemPointerSoldier ) + { + pOldSoldier = gpItemPointerSoldier; + } + else + { + // it came from either the currently selected merc, or the sector inventory + if ( fMapInventoryItem || ( bSelectedInfoChar == -1 ) ) + { + pOldSoldier = NULL; + } + else + { + pOldSoldier = MercPtrs[ gCharactersList[ bSelectedInfoChar ].usSolID ]; + } + } + + + // if another merc had it previously + if ( pOldSoldier != NULL ) + { + // disallow passing items to a merc not in the same sector + if ( pNewSoldier->sSectorX != pOldSoldier->sSectorX || + pNewSoldier->sSectorY != pOldSoldier->sSectorY || + pNewSoldier->bSectorZ != pOldSoldier->bSectorZ ) + { + return( FALSE ); + } + + // if on the road + if ( pNewSoldier->fBetweenSectors ) + { + // other guy must also be on the road... + if ( !pOldSoldier->fBetweenSectors ) + { + return( FALSE ); + } + + // only exchanges between those is the same squad or vehicle are permitted + if ( pNewSoldier->bAssignment != pOldSoldier->bAssignment ) + { + return( FALSE ); + } + + // if in vehicles, make sure it's the same one + if ( ( pNewSoldier->bAssignment == VEHICLE ) && ( pNewSoldier->iVehicleId != pOldSoldier->iVehicleId ) ) + { + return( FALSE ); + } + } + } + + + // passed all tests + return( TRUE ); +} + + + +void GoToNextCharacterInList( void ) +{ + INT32 iCounter = 0, iCount = 0; + + + if( fShowDescriptionFlag == TRUE ) + { + return; + } + + if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + { + AbortMovementPlottingMode( ); + } + + // is the current guy invalid or the first one? + if( ( bSelectedInfoChar == -1 )|| ( bSelectedInfoChar == MAX_CHARACTER_COUNT ) ) + { + iCount = 0; + } + else + { + iCount = bSelectedInfoChar + 1; + } + + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + if ( ( gCharactersList[ iCount ].fValid ) && ( iCount < MAX_CHARACTER_COUNT ) && ValidSelectableCharForNextOrPrev( iCount ) ) + { + ChangeSelectedInfoChar( ( INT8 )iCount, TRUE ); + break; + } + else + { + iCount++; + + if( iCount >= MAX_CHARACTER_COUNT ) + { + iCount = 0; + } + } + } +} + + +void GoToPrevCharacterInList( void ) +{ + INT32 iCounter = 0, iCount = 0; + + + if( fShowDescriptionFlag == TRUE ) + { + return; + } + + if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + { + AbortMovementPlottingMode( ); + } + + // is the current guy invalid or the first one? + if( ( bSelectedInfoChar == -1 ) || ( bSelectedInfoChar == 0 ) ) + { + iCount = MAX_CHARACTER_COUNT; + } + else + { + iCount = bSelectedInfoChar - 1; + } + + // now run through the list and find first prev guy + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + if ( ( gCharactersList[ iCount ].fValid ) && ( iCount < MAX_CHARACTER_COUNT ) && ValidSelectableCharForNextOrPrev( iCount ) ) + { + ChangeSelectedInfoChar( ( INT8 )iCount, TRUE ); + break; + } + else + { + iCount--; + + if( iCount < 0 ) + { + // was FIRST_VEHICLE + iCount = MAX_CHARACTER_COUNT; + } + } + } +} + + + +void HandleMinerEvent( UINT8 bMinerNumber, INT16 sSectorX, INT16 sSectorY, INT16 sQuoteNumber, BOOLEAN fForceMapscreen ) +{ + BOOLEAN fFromMapscreen = FALSE; + + + if ( guiCurrentScreen == MAP_SCREEN ) + { + fFromMapscreen = TRUE; + } + else + { + // if transition to mapscreen is required + if ( fForceMapscreen ) + { + // switch to mapscreen so we can flash the mine sector the guy is talking about + EnterMapScreen( ); + fFromMapscreen = TRUE; + } + } + + if ( fFromMapscreen ) + { + // if not showing map surface level + if ( iCurrentMapSectorZ != 0 ) + { + // switch to it, because the miner locators wouldn't show up if we're underground while they speak + ChangeSelectedMapSector( sSelMapX, sSelMapY, 0 ); + } + + // set up the mine sector flasher + gsSectorLocatorX = sSectorX; + gsSectorLocatorY = sSectorY; + + fMapPanelDirty = TRUE; + + // post dialogue events for miners to say this quote and flash the sector where his mine is + CharacterDialogueWithSpecialEvent( ( UINT8 )uiExternalFaceProfileIds[ bMinerNumber ], sQuoteNumber, bMinerNumber , DIALOGUE_EXTERNAL_NPC_UI , FALSE , FALSE , DIALOGUE_SPECIAL_EVENT_MINESECTOREVENT, START_RED_SECTOR_LOCATOR, 1 ); + CharacterDialogue( ( UINT8 )uiExternalFaceProfileIds[ bMinerNumber ], sQuoteNumber, ( UINT8 )( UINT8 )uiExternalStaticNPCFaces[ bMinerNumber ], DIALOGUE_EXTERNAL_NPC_UI, FALSE , FALSE ); + CharacterDialogueWithSpecialEvent( ( UINT8 )uiExternalFaceProfileIds[ bMinerNumber ], sQuoteNumber, bMinerNumber , DIALOGUE_EXTERNAL_NPC_UI , FALSE , FALSE , DIALOGUE_SPECIAL_EVENT_MINESECTOREVENT, STOP_RED_SECTOR_LOCATOR, 1 ); + } + else // stay in tactical + { + // no need to to highlight mine sector + CharacterDialogue( ( UINT8 )uiExternalFaceProfileIds[ bMinerNumber ], sQuoteNumber, ( UINT8 )( UINT8 )uiExternalStaticNPCFaces[ bMinerNumber ], DIALOGUE_EXTERNAL_NPC_UI, FALSE , FALSE ); + } +} + + +void SetUpAnimationOfMineSectors( INT32 iEvent ) +{ + // set up the animation of mine sectors + switch( iEvent ) + { + case START_RED_SECTOR_LOCATOR: + gubBlitSectorLocatorCode = LOCATOR_COLOR_RED; + break; + + case START_YELLOW_SECTOR_LOCATOR: + gubBlitSectorLocatorCode = LOCATOR_COLOR_YELLOW; + break; + + case STOP_RED_SECTOR_LOCATOR: + case STOP_YELLOW_SECTOR_LOCATOR: + TurnOffSectorLocator(); + break; + } +} + +void ShutDownUserDefineHelpTextRegions( void ) +{ + // dirty the tactical panel + fInterfacePanelDirty = DIRTYLEVEL2; + SetRenderFlags( RENDER_FLAG_FULL ); + + //dirty the map panel + StopMapScreenHelpText( ); + + //r eset tactical flag too + StopShowingInterfaceFastHelpText( ); +} + + +// thsi will setup the fast help text regions that are unrelated to mouse regions +// user is to pass in the x,y position of the box, the width to wrap the strings and the string itself +BOOLEAN SetUpFastHelpListRegions( INT32 iXPosition[], INT32 iYPosition[], INT32 iWidth[], STR16 sString[], INT32 iSize ) +{ + INT32 iCounter = 0; + + // reset the size + giSizeOfInterfaceFastHelpTextList = 0; + + for( iCounter = 0; iCounter < iSize; iCounter++ ) + { + + // forgiving way of making sure we don't go too far + CHECKF( iCounter < MAX_MAPSCREEN_FAST_HELP ); + + // now copy over info + pFastHelpMapScreenList[ iCounter ].iX = iXPosition[ iCounter ]; + pFastHelpMapScreenList[ iCounter ].iY = iYPosition[ iCounter ]; + pFastHelpMapScreenList[ iCounter ].iW = iWidth[ iCounter ]; + + // copy string + wcscpy( pFastHelpMapScreenList[ iCounter ].FastHelpText, sString[ iCounter ] ); + + // update the size + giSizeOfInterfaceFastHelpTextList = iCounter + 1; + } + + return( TRUE ); +} + + +// handle the actual showing of the interface fast help text +void HandleShowingOfTacticalInterfaceFastHelpText( void ) +{ + static BOOLEAN fTextActive = FALSE; + + if( fInterfaceFastHelpTextActive ) + { + DisplayFastHelpRegions( pFastHelpMapScreenList, giSizeOfInterfaceFastHelpTextList ); + + PauseGame(); + + // lock out the screen + SetUpShutDownMapScreenHelpTextScreenMask( ); + + gfIgnoreScrolling = TRUE; + + // the text is active + fTextActive = TRUE; + + } + else if( ( fInterfaceFastHelpTextActive == FALSE ) && ( fTextActive ) ) + { + fTextActive = FALSE; + UnPauseGame(); + gfIgnoreScrolling = FALSE; + + // shut down + ShutDownUserDefineHelpTextRegions( ); + } + + return; +} + +// start showing fast help text +void StartShowingInterfaceFastHelpText( void ) +{ + fInterfaceFastHelpTextActive = TRUE; +} + +// stop showing interface fast help text +void StopShowingInterfaceFastHelpText( void ) +{ + fInterfaceFastHelpTextActive = FALSE; +} + + +// is the interface text up? +BOOLEAN IsTheInterfaceFastHelpTextActive( void ) +{ + return( fInterfaceFastHelpTextActive ); +} + + +// display all the regions in the list +void DisplayFastHelpRegions( FASTHELPREGION *pRegion, INT32 iSize ) +{ + INT32 iCounter = 0; + + // run through and show all the regions + for( iCounter = 0; iCounter < iSize; iCounter++ ) + { + DisplayUserDefineHelpTextRegions( &( pRegion[ iCounter ] ) ); + } + + return; +} + +// show one region +void DisplayUserDefineHelpTextRegions( FASTHELPREGION *pRegion ) +{ + UINT16 usFillColor; + INT32 iX,iY,iW,iH; + INT32 iNumberOfLines = 1; + UINT8 *pDestBuf; + UINT32 uiDestPitchBYTES; + + + // grab the color for the background region + usFillColor = Get16BPPColor(FROMRGB(250, 240, 188)); + + + iX = pRegion->iX; + iY = pRegion->iY; + // get the width and height of the string + iW = (INT32)( pRegion->iW ) + 14; + iH = IanWrappedStringHeight( ( UINT16 )iX, ( UINT16 )iY, ( UINT16 )( pRegion->iW ), 0, FONT10ARIAL, FONT_BLACK, pRegion->FastHelpText, FONT_BLACK, TRUE, 0 ); + + // tack on the outer border + iH += 14; + + // gone not far enough? + if ( iX < 0 ) + iX = 0; + + // gone too far + if ( ( pRegion->iX + iW ) >= SCREEN_WIDTH ) + iX = (SCREEN_WIDTH - iW - 4); + + // what about the y value? + iY = (INT32)pRegion->iY - ( iH * 3 / 4); + + // not far enough + if (iY < 0) + iY = 0; + + // too far + if ( (iY + iH) >= SCREEN_HEIGHT ) + iY = (SCREEN_HEIGHT - iH - 15); + + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); + RectangleDraw( TRUE, iX + 1, iY + 1, iX + iW - 1, iY + iH - 1, Get16BPPColor( FROMRGB( 65, 57, 15 ) ), pDestBuf ); + RectangleDraw( TRUE, iX, iY, iX + iW - 2, iY + iH - 2, Get16BPPColor( FROMRGB( 227, 198, 88 ) ), pDestBuf ); + UnLockVideoSurface( FRAME_BUFFER ); + ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 ); + ShadowVideoSurfaceRect( FRAME_BUFFER, iX + 2, iY + 2, iX + iW - 3, iY + iH - 3 ); + + // fillt he video surface areas + //ColorFillVideoSurfaceArea(FRAME_BUFFER, iX, iY, (iX + iW), (iY + iH), 0); + //ColorFillVideoSurfaceArea(FRAME_BUFFER, (iX + 1), (iY + 1), (iX + iW - 1), (iY + iH - 1), usFillColor); + + SetFont( FONT10ARIAL ); + SetFontForeground( FONT_BEIGE ); + + iH = ( INT32 )DisplayWrappedString( ( INT16 )( iX + 10 ), ( INT16 )( iY + 6 ), ( INT16 )pRegion->iW, 0, FONT10ARIAL, FONT_BEIGE, pRegion->FastHelpText, FONT_NEARBLACK, TRUE, 0 ); + + iHeightOfInitFastHelpText = iH + 20; + + InvalidateRegion( iX, iY, (iX + iW) , (iY + iH + 20 ) ); + +} + +void DisplayFastHelpForInitialTripInToMapScreen( FASTHELPREGION *pRegion ) +{ + + + + + if( gTacticalStatus.fDidGameJustStart ) + { + if( AnyMercsHired() == FALSE ) + { + return; + } + + HandleDisplayOfExitToTacticalMessageForFirstEntryToMapScreen( ); +// DEF: removed cause the help screen will replace the help screen +// DisplayFastHelpRegions( &pFastHelpMapScreenList[ 9 ], 1 ); + + } + else + { + DisplayFastHelpRegions( pFastHelpMapScreenList, giSizeOfInterfaceFastHelpTextList ); + } + + SetUpShutDownMapScreenHelpTextScreenMask( ); + + return; +} + + +void DisplayMapScreenFastHelpList( void ) +{ + INT32 iCounter = 0; + + DisplayFastHelpForInitialTripInToMapScreen( &pFastHelpMapScreenList[ iCounter ] ); + + return; +} + + +void SetUpMapScreenFastHelpText( void ) +{ + INT32 iCounter = 0; + + // now run through and display all the fast help text for the mapscreen functional regions + for( iCounter = 0; iCounter < NUMBER_OF_MAPSCREEN_HELP_MESSAGES; iCounter++ ) + { + pFastHelpMapScreenList[ iCounter ].iX = pMapScreenFastHelpLocationList[ iCounter ].iX; + pFastHelpMapScreenList[ iCounter ].iY = pMapScreenFastHelpLocationList[ iCounter ].iY; + pFastHelpMapScreenList[ iCounter ].iW = pMapScreenFastHelpWidthList[ iCounter ]; + wcscpy( pFastHelpMapScreenList[ iCounter ].FastHelpText, pMapScreenFastHelpTextList[ iCounter ] ); + } + +// DEF: removed cause the help screen will replace the help screen +/* + pFastHelpMapScreenList[ 9 ].iX = pMapScreenFastHelpLocationList[ 9 ].iX; + pFastHelpMapScreenList[ 9 ].iY = pMapScreenFastHelpLocationList[ 9 ].iY; + pFastHelpMapScreenList[ 9 ].iW = pMapScreenFastHelpWidthList[ 9 ]; + wcscpy( pFastHelpMapScreenList[ 9 ].FastHelpText, pMapScreenFastHelpTextList[ 9 ] ); +*/ + return; +} + +void StopMapScreenHelpText( void ) +{ + fShowMapScreenHelpText = FALSE; + fTeamPanelDirty = TRUE; + fMapPanelDirty = TRUE; + fCharacterInfoPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; + + SetUpShutDownMapScreenHelpTextScreenMask( ); + return; +} + +BOOLEAN IsMapScreenHelpTextUp( void ) +{ + return( fShowMapScreenHelpText ); +} + +void SetUpShutDownMapScreenHelpTextScreenMask( void ) +{ + static BOOLEAN fCreated = FALSE; + + // create or destroy the screen mask as needed + if( ( ( fShowMapScreenHelpText == TRUE ) || ( fInterfaceFastHelpTextActive == TRUE ) ) && ( fCreated == FALSE ) ) + { + if( gTacticalStatus.fDidGameJustStart ) + { + MSYS_DefineRegion( &gMapScreenHelpTextMask , ( INT16 )( pMapScreenFastHelpLocationList[ 9 ].iX ), ( INT16 )( pMapScreenFastHelpLocationList[ 9 ].iY ), ( INT16 )( pMapScreenFastHelpLocationList[ 9 ].iX + pMapScreenFastHelpWidthList[ 9 ] ), ( INT16 )( pMapScreenFastHelpLocationList[ 9 ].iY + iHeightOfInitFastHelpText ), MSYS_PRIORITY_HIGHEST, + MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MapScreenHelpTextScreenMaskBtnCallback ); + } + else + { + MSYS_DefineRegion( &gMapScreenHelpTextMask , 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGHEST, + MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MapScreenHelpTextScreenMaskBtnCallback ); + } + + fCreated = TRUE; + + } + else if( ( fShowMapScreenHelpText == FALSE ) && ( fInterfaceFastHelpTextActive == FALSE ) && ( fCreated == TRUE ) ) + { + MSYS_RemoveRegion( &gMapScreenHelpTextMask ); + + fCreated = FALSE; + } +} + + +void MapScreenHelpTextScreenMaskBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ) +{ + if( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP ) + { + // stop showing + ShutDownUserDefineHelpTextRegions( ); + } + else if( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP ) + { + // stop showing + ShutDownUserDefineHelpTextRegions( ); + } +} + + +BOOLEAN IsSoldierSelectedForMovement( SOLDIERTYPE *pSoldier ) +{ + INT32 iCounter = 0; + + // run through the list and turn this soldiers value on + for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ ) + { + if( ( pSoldierMovingList[ iCounter ] == pSoldier ) && ( fSoldierIsMoving[ iCounter ] ) ) + { + return ( TRUE ); + } + } + return( FALSE ); +} + +BOOLEAN IsSquadSelectedForMovement( INT32 iSquadNumber ) +{ + INT32 iCounter = 0; + + // run through squad list and set them on + for( iCounter = 0; iCounter < giNumberOfSquadsInSectorMoving; iCounter++ ) + { + if( ( iSquadMovingList[ iCounter ] == iSquadNumber ) && ( fSquadIsMoving[ iCounter ] ) ) + { + return( TRUE ); + } + } + + return( FALSE ); +} + + +BOOLEAN IsVehicleSelectedForMovement( INT32 iVehicleId ) +{ + INT32 iCounter = 0; + + // run through squad list and set them on + for( iCounter = 0; iCounter < giNumberOfVehiclesInSectorMoving; iCounter++ ) + { + if( ( iVehicleMovingList[ iCounter ] == iVehicleId ) && ( fVehicleIsMoving[ iCounter ] ) ) + { + return( TRUE ); + } + } + return( FALSE ); +} + + + +void SelectSoldierForMovement( SOLDIERTYPE *pSoldier ) +{ + INT32 iCounter = 0; + + if( pSoldier == NULL ) + { + return; + } + + // run through the list and turn this soldiers value on + for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ ) + { + if( pSoldierMovingList[ iCounter ] == pSoldier ) + { + // turn the selected soldier ON + fSoldierIsMoving[ iCounter ] = TRUE; + break; + } + } +} + +void DeselectSoldierForMovement( SOLDIERTYPE *pSoldier ) +{ + INT32 iCounter = 0; + + if( pSoldier == NULL ) + { + return; + } + + // run through the list and turn this soldier's value on + for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ ) + { + if( pSoldierMovingList[ iCounter ] == pSoldier ) + { + // turn the selected soldier off + fSoldierIsMoving[ iCounter ] = FALSE; + break; + } + } +} + + +void SelectSquadForMovement( INT32 iSquadNumber ) +{ + INT32 iCounter = 0, iCount = 0; + BOOLEAN fSomeCantMove = FALSE; + SOLDIERTYPE *pSoldier = NULL; + BOOLEAN fFirstFailure; + + + // run through squad list and set them on + for( iCounter = 0; iCounter < giNumberOfSquadsInSectorMoving; iCounter++ ) + { + if( iSquadMovingList[ iCounter ] == iSquadNumber ) + { + // found it + + fFirstFailure = TRUE; + + // try to select everyone in squad + for( iCount = 0; iCount < NUMBER_OF_SOLDIERS_PER_SQUAD; iCount++ ) + { + pSoldier = Squad[ iSquadNumber ][ iCount ]; + + if ( pSoldier && pSoldier->bActive ) + { + // is he able & allowed to move? (Report only the first reason for failure encountered) + if ( CanMoveBoxSoldierMoveStrategically( pSoldier, fFirstFailure ) ) + { + SelectSoldierForMovement( pSoldier ); + } + else + { + fSomeCantMove = TRUE; + fFirstFailure = FALSE; + } + } + } + + if ( !fSomeCantMove ) + { + fSquadIsMoving[ iCounter ] = TRUE; + } + + break; + } + } +} + + + +void DeselectSquadForMovement( INT32 iSquadNumber ) +{ + INT32 iCounter = 0, iCount = 0; + SOLDIERTYPE *pSoldier = NULL; + + // run through squad list and set them off + for( iCounter = 0; iCounter < giNumberOfSquadsInSectorMoving; iCounter++ ) + { + if( iSquadMovingList[ iCounter ] == iSquadNumber ) + { + // found it + fSquadIsMoving[ iCounter ] = FALSE; + + // now deselect everyone in squad + for( iCount = 0; iCount < NUMBER_OF_SOLDIERS_PER_SQUAD; iCount++ ) + { + pSoldier = Squad[ iSquadNumber ][ iCount ]; + + if ( pSoldier && pSoldier->bActive ) + { + DeselectSoldierForMovement( pSoldier ); + } + } + + break; + } + } +} + + +BOOLEAN AllSoldiersInSquadSelected( INT32 iSquadNumber ) +{ + INT32 iCounter = 0, iCount = 0; + + // is everyone on this squad moving? + for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ ) + { + if( pSoldierMovingList[ iCounter ]->bAssignment == ( INT8 )iSquadNumber ) + { + if( fSoldierIsMoving[ iCounter ] == FALSE ) + { + return( FALSE ); + } + } + } + + return( TRUE ); +} + + + +void SelectVehicleForMovement( INT32 iVehicleId, BOOLEAN fAndAllOnBoard ) +{ + INT32 iCounter = 0, iCount = 0; + SOLDIERTYPE *pPassenger = NULL; + BOOLEAN fHasDriver = FALSE; + BOOLEAN fFirstFailure; + + + // run through vehicle list and set them on + for( iCounter = 0; iCounter < giNumberOfVehiclesInSectorMoving; iCounter++ ) + { + if( iVehicleMovingList[ iCounter ] == iVehicleId ) + { + // found it + + fFirstFailure = TRUE; + + for( iCount = 0; iCount < 10; iCount++ ) + { + pPassenger = pVehicleList[ iVehicleId ].pPassengers[ iCount ]; + + if ( fAndAllOnBoard ) + { + // try to select everyone in vehicle + + if ( pPassenger && pPassenger->bActive ) + { + // is he able & allowed to move? + if ( CanMoveBoxSoldierMoveStrategically( pPassenger, fFirstFailure ) ) + { + SelectSoldierForMovement( pPassenger ); + } + else + { + fFirstFailure = FALSE; + } + } + } + + if( IsSoldierSelectedForMovement( pPassenger ) ) + { + fHasDriver = TRUE; + } + } + + // vehicle itself can only move if at least one passenger can move and is moving! + if ( fHasDriver ) + { + fVehicleIsMoving[ iCounter ] = TRUE; + } + + break; + } + } +} + +void DeselectVehicleForMovement( INT32 iVehicleId ) +{ + INT32 iCounter = 0, iCount = 0; + SOLDIERTYPE *pPassenger = NULL; + + + // run through vehicle list and set them off + for( iCounter = 0; iCounter < giNumberOfVehiclesInSectorMoving; iCounter++ ) + { + if( iVehicleMovingList[ iCounter ] == iVehicleId ) + { + // found it + fVehicleIsMoving[ iCounter ] = FALSE; + + // now deselect everyone in vehicle + for( iCount = 0; iCount < 10 ; iCount++ ) + { + pPassenger = pVehicleList[ iVehicleId ].pPassengers[ iCount ]; + + if ( pPassenger && pPassenger->bActive ) + { + DeselectSoldierForMovement( pPassenger ); + } + } + + break; + } + } +} + + +INT32 HowManyMovingSoldiersInVehicle( INT32 iVehicleId ) +{ + INT32 iNumber = 0, iCounter = 0; + + for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ ) + { + // is he in the right vehicle + if( ( pSoldierMovingList[ iCounter ] ->bAssignment == VEHICLE )&&( pSoldierMovingList[ iCounter ] ->iVehicleId == iVehicleId ) ) + { + // if he moving? + if ( fSoldierIsMoving[ iCounter ] ) + { + // ok, another one in the vehicle that is going to move + iNumber++; + } + } + } + + return( iNumber ); +} + +INT32 HowManyMovingSoldiersInSquad( INT32 iSquadNumber ) +{ + INT32 iNumber = 0, iCounter = 0; + + for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ ) + { + // is he in the right squad + if( pSoldierMovingList[ iCounter ] ->bAssignment == iSquadNumber ) + { + // if he moving? + if ( fSoldierIsMoving[ iCounter ] ) + { + // ok, another one in the squad that is going to move + iNumber++; + } + } + } + + return( iNumber ); +} + + +// try to add this soldier to the moving lists +void AddSoldierToMovingLists( SOLDIERTYPE *pSoldier ) +{ + INT32 iCounter = 0; + + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + if( pSoldierMovingList[ iCounter ] == pSoldier ) + { + // found + return; + } + else if( pSoldierMovingList[ iCounter ] == NULL ) + { + // found a free slot + pSoldierMovingList[ iCounter ] = pSoldier; + fSoldierIsMoving[ iCounter ] = FALSE; + + giNumberOfSoldiersInSectorMoving++; + return; + } + } + return; +} + + +// try to add this soldier to the moving lists +void AddSquadToMovingLists( INT32 iSquadNumber ) +{ + INT32 iCounter = 0; + + if( iSquadNumber == -1 ) + { + // invalid squad + return; + } + + for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ ) + { + if( iSquadMovingList[ iCounter ] == iSquadNumber ) + { + // found + return; + } + if( iSquadMovingList[ iCounter ] == -1 ) + { + // found a free slot + iSquadMovingList[ iCounter ] = iSquadNumber; + fSquadIsMoving[ iCounter ] = FALSE; + + giNumberOfSquadsInSectorMoving++; + return; + } + } + return; +} + + +// try to add this soldier to the moving lists +void AddVehicleToMovingLists( INT32 iVehicleId ) +{ + INT32 iCounter = 0; + + if( iVehicleId == -1 ) + { + // invalid squad + return; + } + + for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ ) + { + if( iVehicleMovingList[ iCounter ] == iVehicleId ) + { + // found + return; + } + if( iVehicleMovingList[ iCounter ] == -1 ) + { + // found a free slot + iVehicleMovingList[ iCounter ] = iVehicleId; + fVehicleIsMoving[ iCounter ] = FALSE; + + giNumberOfVehiclesInSectorMoving++; + return; + } + } + return; +} + + + +void InitializeMovingLists( void ) +{ + INT32 iCounter = 0; + + + giNumberOfSoldiersInSectorMoving = 0; + giNumberOfSquadsInSectorMoving = 0; + giNumberOfVehiclesInSectorMoving = 0; + + // init the soldiers + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + // soldier is NOT moving + pSoldierMovingList[ iCounter ] = NULL; + // turn the selected soldier off + fSoldierIsMoving[ iCounter ] = FALSE; + } + + + // init the squads + for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ ) + { + // reset squad value + iSquadMovingList[ iCounter ] = -1; + // turn it off + fSquadIsMoving[ iCounter ] = FALSE; + } + + // init the vehicles + for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ ) + { + // reset squad value + iVehicleMovingList[ iCounter ] = -1; + // turn it off + fVehicleIsMoving[ iCounter ] = FALSE; + } + + return; +} + + + +BOOLEAN IsAnythingSelectedForMoving( void ) +{ + INT32 iCounter = 0; + + + // check soldiers + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + if ( ( pSoldierMovingList[ iCounter ] != NULL ) && fSoldierIsMoving[ iCounter ] ) + { + return( TRUE ); + } + } + + + // init the squads + for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ ) + { + if ( ( iSquadMovingList[ iCounter ] != -1 ) && fSquadIsMoving[ iCounter ] ) + { + return( TRUE ); + } + } + + // init the vehicles + for( iCounter = 0; iCounter < NUMBER_OF_SQUADS; iCounter++ ) + { + if ( ( iVehicleMovingList[ iCounter ] != -1 ) && fVehicleIsMoving[ iCounter ] ) + { + return( TRUE ); + } + } + + return( FALSE ); +} + + + +void CreateDestroyMovementBox( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ ) +{ + static BOOLEAN fCreated = FALSE; + + + // not allowed for underground movement! + Assert( sSectorZ == 0 ); + + if( ( fShowMapScreenMovementList == TRUE ) && ( fCreated == FALSE ) ) + { + fCreated = TRUE; + + // create the box and mouse regions + CreatePopUpBoxForMovementBox( ); + BuildMouseRegionsForMoveBox( ); + CreateScreenMaskForMoveBox( ); + fMapPanelDirty = TRUE; + } + else if( ( fShowMapScreenMovementList == FALSE ) && ( fCreated == TRUE ) ) + { + fCreated = FALSE; + + // destroy the box and mouse regions + ClearMouseRegionsForMoveBox( ); + RemoveBox( ghMoveBox ); + ghMoveBox = -1; + RemoveScreenMaskForMoveBox( ); + fMapPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; // really long move boxes can overlap bottom panel + } + +} + + + +void SetUpMovingListsForSector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ ) +{ + INT32 iCounter = 0; + SOLDIERTYPE *pSoldier = NULL; + + + // not allowed for underground movement! + Assert( sSectorZ == 0 ); + + + // clear the lists + InitializeMovingLists(); + + + // note that Skyrider can't be moved using the move box, and won't appear because the helicoprer is not in the char list + + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + if( gCharactersList[ iCounter ].fValid ) + { + pSoldier = MercPtrs[ gCharactersList[ iCounter ].usSolID ]; + + if( ( pSoldier->bActive ) && + ( pSoldier->bAssignment != IN_TRANSIT ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && + ( pSoldier->sSectorX == sSectorX ) && ( pSoldier->sSectorY == sSectorY ) && ( pSoldier->bSectorZ == sSectorZ ) ) + { + if ( pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) + { + // vehicle + // if it can move (can't be empty) + if ( GetNumberInVehicle( pSoldier->bVehicleID ) > 0 ) + { + // add vehicle + AddVehicleToMovingLists( pSoldier->bVehicleID ); + } + } + else // soldier + { + // alive, not aboard Skyrider (airborne or not!) + if ( ( pSoldier->bLife >= OKLIFE ) && + ( ( pSoldier->bAssignment != VEHICLE ) || ( pSoldier->iVehicleId != iHelicopterVehicleId ) ) ) + { + // add soldier + AddSoldierToMovingLists( pSoldier ); + + // if on a squad, + if ( pSoldier->bAssignment < ON_DUTY ) + { + // add squad (duplicates ok, they're ignored inside the function) + AddSquadToMovingLists( pSoldier->bAssignment ); + } + } + } + } + } + } + + fShowMapScreenMovementList = TRUE; + CreateDestroyMovementBox( sSectorX, sSectorY, sSectorZ ); +} + + + +void CreatePopUpBoxForMovementBox( void ) +{ + SGPPoint Position; + SGPRect Dimensions; + + // create the pop up box and mouse regions for movement list + + // create basic box + CreatePopUpBox(&ghMoveBox, AssignmentDimensions, MovePosition, (POPUP_BOX_FLAG_CLIP_TEXT|POPUP_BOX_FLAG_RESIZE )); + + // which buffer will box render to + SetBoxBuffer(ghMoveBox, FRAME_BUFFER); + + // border type? + SetBorderType(ghMoveBox,guiPOPUPBORDERS); + + // background texture + SetBackGroundSurface(ghMoveBox, guiPOPUPTEX); + + // margin sizes + SetMargins( ghMoveBox, 6, 6, 4, 4 ); + + // space between lines + SetLineSpace(ghMoveBox, 2); + + // set current box to this one + SetCurrentBox( ghMoveBox ); + + // add strings + AddStringsToMoveBox( ); + + + // set font type + SetBoxFont(ghMoveBox, MAP_SCREEN_FONT); + + // set highlight color + SetBoxHighLight(ghMoveBox, FONT_WHITE); + + // unhighlighted color + SetBoxForeground(ghMoveBox, FONT_LTGREEN); + + // make the header line WHITE + SetBoxLineForeground( ghMoveBox, 0, FONT_WHITE ); + + // make the done and cancel lines YELLOW + SetBoxLineForeground( ghMoveBox, GetNumberOfLinesOfTextInBox( ghMoveBox ) - 1, FONT_YELLOW ); + + if ( IsAnythingSelectedForMoving() ) + { + SetBoxLineForeground( ghMoveBox, GetNumberOfLinesOfTextInBox( ghMoveBox ) - 2, FONT_YELLOW ); + } + + // background color + SetBoxBackground(ghMoveBox, FONT_BLACK); + + // shaded color..for darkened text + SetBoxShade( ghMoveBox, FONT_BLACK ); + + + // resize box to text + ResizeBoxToText( ghMoveBox ); + + GetBoxPosition( ghMoveBox, &Position); + GetBoxSize( ghMoveBox, &Dimensions ); + + // adjust position to try to keep it in the map area as best as possible + if ( Position.iX + Dimensions.iRight >= ( MAP_VIEW_START_X + MAP_VIEW_WIDTH ) ) + { + Position.iX = max( MAP_VIEW_START_X, ( MAP_VIEW_START_X + MAP_VIEW_WIDTH ) - Dimensions.iRight ); + SetBoxPosition( ghMoveBox, Position ); + } + + if ( Position.iY + Dimensions.iBottom >= ( MAP_VIEW_START_Y + MAP_VIEW_HEIGHT ) ) + { + Position.iY = max( MAP_VIEW_START_Y, ( MAP_VIEW_START_Y + MAP_VIEW_HEIGHT ) - Dimensions.iBottom ); + SetBoxPosition( ghMoveBox, Position ); + } +} + + + +void AddStringsToMoveBox( void ) +{ + INT32 iCount = 0, iCountB = 0; + CHAR16 sString[ 128 ], sStringB[ 128 ]; + UINT32 hStringHandle; + BOOLEAN fFirstOne = TRUE; + + + // set the current box + SetCurrentBox( ghMoveBox ); + + // clear all the strings out of the box + RemoveAllCurrentBoxStrings(); + + + // add title + GetShortSectorString( sSelMapX, sSelMapY, sStringB ); + swprintf( sString, L"%s %s", pMovementMenuStrings[ 0 ], sStringB ); + AddMonoString(&hStringHandle, sString ); + + + // blank line + AddMonoString(&hStringHandle, L"" ); + + + // add squads + for( iCount = 0; iCount < giNumberOfSquadsInSectorMoving; iCount++ ) + { + // add this squad, now add all the grunts in it + if( fSquadIsMoving[ iCount ] ) + { + swprintf( sString, L"*%s*", pSquadMenuStrings[iSquadMovingList[ iCount ] ] ); + } + else + { + swprintf( sString, L"%s", pSquadMenuStrings[iSquadMovingList[ iCount ] ] ); + } + AddMonoString(&hStringHandle, sString ); + + // now add all the grunts in it + for( iCountB = 0; iCountB < giNumberOfSoldiersInSectorMoving; iCountB++ ) + { + if( pSoldierMovingList[ iCountB ] -> bAssignment == iSquadMovingList[ iCount ] ) + { + // add mercs in squads + if( IsSoldierSelectedForMovement( pSoldierMovingList[ iCountB ] ) == TRUE ) + { + swprintf( sString, L" *%s*", pSoldierMovingList[ iCountB ]->name ); + } + else + { + swprintf( sString, L" %s", pSoldierMovingList[ iCountB ]->name ); + } + AddMonoString(&hStringHandle, sString ); + } + } + } + + + // add vehicles + for( iCount = 0; iCount < giNumberOfVehiclesInSectorMoving; iCount++ ) + { + // add this vehicle + if( fVehicleIsMoving[ iCount ] ) + { + swprintf( sString, L"*%s*", pVehicleStrings[ pVehicleList[ iVehicleMovingList[ iCount ] ].ubVehicleType ] ); + } + else + { + swprintf( sString, L"%s", pVehicleStrings[ pVehicleList[ iVehicleMovingList[ iCount ] ].ubVehicleType ] ); + } + AddMonoString(&hStringHandle, sString ); + + // now add all the grunts in it + for( iCountB = 0; iCountB < giNumberOfSoldiersInSectorMoving; iCountB++ ) + { + if( ( pSoldierMovingList[ iCountB ] -> bAssignment == VEHICLE ) &&( pSoldierMovingList[ iCountB ] -> iVehicleId == iVehicleMovingList[ iCount ] ) ) + { + // add mercs in vehicles + if( IsSoldierSelectedForMovement( pSoldierMovingList[ iCountB ] ) == TRUE ) + { + swprintf( sString, L" *%s*", pSoldierMovingList[ iCountB ]->name ); + } + else + { + swprintf( sString, L" %s", pSoldierMovingList[ iCountB ]->name ); + } + AddMonoString(&hStringHandle, sString ); + } + } + } + + + fFirstOne = TRUE; + + // add "other" soldiers heading, once, if there are any + for( iCount = 0; iCount < giNumberOfSoldiersInSectorMoving; iCount++ ) + { + // not on duty, not in a vehicle + if( ( pSoldierMovingList[ iCount ]->bAssignment >= ON_DUTY ) && ( pSoldierMovingList[ iCount ]->bAssignment != VEHICLE ) ) + { + if ( fFirstOne ) + { + // add OTHER header line + if( AllOtherSoldiersInListAreSelected( ) ) + { + swprintf( sString, L"*%s*", pMovementMenuStrings[ 3 ] ); + } + else + { + swprintf( sString, L"%s", pMovementMenuStrings[ 3 ] ); + } + AddMonoString(&hStringHandle, sString ); + + fFirstOne = FALSE; + } + + // add OTHER soldiers (not on duty nor in a vehicle) + if( IsSoldierSelectedForMovement( pSoldierMovingList[ iCount ] ) == TRUE ) + { + swprintf( sString, L" *%s ( %s )*", pSoldierMovingList[ iCount ]->name, pAssignmentStrings[ pSoldierMovingList[ iCount ]->bAssignment ] ); + } + else + { + swprintf( sString, L" %s ( %s )", pSoldierMovingList[ iCount ]->name, pAssignmentStrings[ pSoldierMovingList[ iCount ]->bAssignment ] ); + } + AddMonoString(&hStringHandle, sString ); + } + } + + + // blank line + AddMonoString(&hStringHandle, L"" ); + + + if ( IsAnythingSelectedForMoving() ) + { + // add PLOT MOVE line + swprintf( sString, L"%s", pMovementMenuStrings[ 1 ] ); + AddMonoString(&hStringHandle, sString ); + } + else + { + // blank line + AddMonoString(&hStringHandle, L"" ); + } + + + // add cancel line + swprintf( sString, L"%s", pMovementMenuStrings[ 2 ] ); + AddMonoString(&hStringHandle, sString ); + + return; +} + + +void BuildMouseRegionsForMoveBox( void ) +{ + INT32 iCounter = 0, iTotalNumberOfLines = 0, iCount = 0, iCountB = 0; + SGPPoint pPosition; + INT32 iBoxWidth = 0; + SGPRect Dimensions; + INT32 iFontHeight = 0; + INT32 iBoxXPosition = 0; + INT32 iBoxYPosition = 0; + BOOLEAN fDefinedOtherRegion = FALSE; + + + // grab height of font + iFontHeight = GetLineSpace( ghMoveBox ) + GetFontHeight( GetBoxFont( ghMoveBox ) ); + + // get x.y position of box + GetBoxPosition( ghMoveBox, &pPosition); + + // grab box x and y position + iBoxXPosition = pPosition.iX; + iBoxYPosition = pPosition.iY + GetTopMarginSize( ghMoveBox ) - 2; // -2 to improve highlighting accuracy between lines + + + // get dimensions..mostly for width + GetBoxSize( ghMoveBox, &Dimensions ); + + // get width + iBoxWidth = Dimensions.iRight; + + SetCurrentBox( ghMoveBox ); + + + // box heading + MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST, + MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK ); + iCounter++; + + // blank line + MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST, + MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK ); + iCounter++; + + // calc total number of "moving" lines in the box + iTotalNumberOfLines = giNumberOfSoldiersInSectorMoving + giNumberOfSquadsInSectorMoving + giNumberOfVehiclesInSectorMoving; + // add the blank lines + iTotalNumberOfLines += iCounter; + + + // now add the strings + while( iCounter < iTotalNumberOfLines ) + { + // define regions for squad lines + for( iCount = 0; iCount < giNumberOfSquadsInSectorMoving; iCount++ ) + { + MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST, + MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback ); + + // set user defines + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter ); + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, SQUAD_REGION ); + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, iCount ); + iCounter++; + + for( iCountB = 0; iCountB < giNumberOfSoldiersInSectorMoving; iCountB++ ) + { + if( pSoldierMovingList[ iCountB ] -> bAssignment == iSquadMovingList[ iCount ] ) + { + MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST, + MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback ); + + // set user defines + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter ); + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, SOLDIER_REGION ); + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, iCountB ); + iCounter++; + } + } + } + + for( iCount = 0; iCount < giNumberOfVehiclesInSectorMoving; iCount++ ) + { + // define regions for vehicle lines + MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST, + MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback ); + + // set user defines + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter ); + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, VEHICLE_REGION ); + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, iCount ); + iCounter++; + + for( iCountB = 0; iCountB < giNumberOfSoldiersInSectorMoving; iCountB++ ) + { + if( ( pSoldierMovingList[ iCountB ] -> bAssignment == VEHICLE ) &&( pSoldierMovingList[ iCountB ] -> iVehicleId == iVehicleMovingList[ iCount ] ) ) + { + MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST, + MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback ); + + // set user defines + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter ); + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, SOLDIER_REGION ); + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, iCountB ); + iCounter++; + } + } + } + + + // define regions for "other" soldiers + for( iCount = 0; iCount < giNumberOfSoldiersInSectorMoving; iCount++ ) + { + // this guy is not in a squad or vehicle + if( ( pSoldierMovingList[ iCount ]->bAssignment >= ON_DUTY )&&( pSoldierMovingList[ iCount ]->bAssignment != VEHICLE ) ) + { + // this line gets place only once... + if( !fDefinedOtherRegion ) + { + MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST, + MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback ); + + // set user defines + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter ); + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, OTHER_REGION ); + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, 0 ); + iCounter++; + + fDefinedOtherRegion = TRUE; + } + + MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST, + MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback ); + + // set user defines + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter ); + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, SOLDIER_REGION ); + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, iCount ); + iCounter++; + } + } + } + + + // blank line + MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST, + MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK ); + iCounter++; + + + if ( IsAnythingSelectedForMoving() ) + { + // DONE line + MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST, + MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback ); + + // set user defines + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter ); + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, DONE_REGION ); + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, 0 ); + iCounter++; + } + else + { + // blank line + MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST, + MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK ); + iCounter++; + } + + // CANCEL line + MSYS_DefineRegion( &gMoveMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + iFontHeight * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + iFontHeight * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST, + MSYS_NO_CURSOR, MoveMenuMvtCallback, MoveMenuBtnCallback ); + + // set user defines + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 0, iCounter ); + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 1, CANCEL_REGION ); + MSYS_SetRegionUserData( &gMoveMenuRegion[ iCounter ], 2, 0 ); + iCounter++; +} + +void ClearMouseRegionsForMoveBox( void ) +{ + INT32 iCounter = 0; + + // run through list of mouse regions + for( iCounter = 0; iCounter < ( INT32 )GetNumberOfLinesOfTextInBox( ghMoveBox ); iCounter++ ) + { + // remove this region + MSYS_RemoveRegion( &gMoveMenuRegion[ iCounter ] ); + } + + return; +} + + + +void MoveMenuMvtCallback(MOUSE_REGION * pRegion, INT32 iReason ) +{ + // mvt callback handler for move box line regions + INT32 iValue = -1; + + + iValue = MSYS_GetRegionUserData( pRegion, 0 ); + + if (iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) + { + // highlight string + HighLightBoxLine( ghMoveBox, iValue ); + } + else if (iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) + { + // unhighlight all strings in box + UnHighLightBox( ghMoveBox ); + } +} + + + +void MoveMenuBtnCallback(MOUSE_REGION * pRegion, INT32 iReason ) +{ + // btn callback handler for move box line regions + INT32 iMoveBoxLine = -1, iRegionType = -1, iListIndex = -1, iClickTime = 0; + SOLDIERTYPE *pSoldier = NULL; + + + iMoveBoxLine = MSYS_GetRegionUserData( pRegion, 0 ); + iRegionType = MSYS_GetRegionUserData( pRegion, 1 ); + iListIndex = MSYS_GetRegionUserData( pRegion, 2 ); + iClickTime = GetJA2Clock(); + + if( ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP ) ) + { + if( iClickTime - giDblClickTimersForMoveBoxMouseRegions[ iMoveBoxLine ] < DBL_CLICK_DELAY_FOR_MOVE_MENU ) + { + // dbl click, and something is selected? + if ( IsAnythingSelectedForMoving() ) + { + // treat like DONE + HandleMoveoutOfSectorMovementTroops( ); + return; + } + } + else + { + giDblClickTimersForMoveBoxMouseRegions[ iMoveBoxLine ] = iClickTime; + + if( iRegionType == SQUAD_REGION ) + { + // is the squad moving + if( fSquadIsMoving[ iListIndex ] == TRUE ) + { + // squad stays + DeselectSquadForMovement( iSquadMovingList[ iListIndex ] ); + } + else + { + // squad goes + SelectSquadForMovement( iSquadMovingList[ iListIndex ] ); + } + } + else if( iRegionType == VEHICLE_REGION ) + { + // is the vehicle moving + if( fVehicleIsMoving[ iListIndex ] == TRUE ) + { + // vehicle stays + DeselectVehicleForMovement( iVehicleMovingList[ iListIndex ] ); + } + else + { + // vehicle goes + SelectVehicleForMovement( iVehicleMovingList[ iListIndex ], AND_ALL_ON_BOARD ); + } + } + else if( iRegionType == OTHER_REGION ) + { + if( AllOtherSoldiersInListAreSelected( ) == TRUE ) + { + // deselect all others in the list + DeselectAllOtherSoldiersInList( ); + } + else + { + // select all others in the list + SelectAllOtherSoldiersInList( ); + } + } + else if( iRegionType == SOLDIER_REGION ) + { + pSoldier = pSoldierMovingList[ iListIndex ]; + + if ( pSoldier->fBetweenSectors ) + { + // we don't allow mercs to change squads or get out of vehicles between sectors, easiest way to handle this + // is to prevent any toggling of individual soldiers on the move at the outset. + DoScreenIndependantMessageBox( pMapErrorString[ 41 ], MSG_BOX_FLAG_OK, NULL ); + return; + } + + // if soldier is currently selected to move + if( IsSoldierSelectedForMovement( pSoldier ) ) + { + // change him to NOT move instead + + if( pSoldier->bAssignment == VEHICLE ) + { + // if he's the only one left moving in the vehicle, deselect whole vehicle + if( HowManyMovingSoldiersInVehicle( pSoldier->iVehicleId ) == 1 ) + { + // whole vehicle stays + DeselectVehicleForMovement( pSoldier->iVehicleId ); + } + else + { + // soldier is staying behind + DeselectSoldierForMovement( pSoldier ); + } + } + else if( pSoldier->bAssignment < ON_DUTY ) + { + // if he's the only one left moving in the squad, deselect whole squad + if( HowManyMovingSoldiersInSquad( pSoldier->bAssignment ) == 1 ) + { + // whole squad stays + DeselectSquadForMovement( pSoldier->bAssignment ); + } + else + { + // soldier is staying behind + DeselectSoldierForMovement( pSoldier ); + } + } + else + { + // soldier is staying behind + DeselectSoldierForMovement( pSoldier ); + } + } + else // currently NOT moving + { + // is he able & allowed to move? (Errors with a reason are reported within) + if ( CanMoveBoxSoldierMoveStrategically( pSoldier, TRUE ) ) + { + // change him to move instead + SelectSoldierForMovement( pSoldier ); + + if( pSoldier->bAssignment < ON_DUTY ) + { + // if everyone in the squad is now selected, select the squad itself + if( AllSoldiersInSquadSelected( pSoldier->bAssignment ) ) + { + SelectSquadForMovement( pSoldier->bAssignment ); + } + } +/* ARM: it's more flexible without this - player can take the vehicle along or not without having to exit it. + else if( pSoldier->bAssignment == VEHICLE ) + { + // his vehicle MUST also go while he's moving, but not necessarily others on board + SelectVehicleForMovement( pSoldier->iVehicleId, VEHICLE_ONLY ); + } +*/ + } + } + } + else if( iRegionType == DONE_REGION ) + { + // is something selected? + if ( IsAnythingSelectedForMoving() ) + { + HandleMoveoutOfSectorMovementTroops( ); + return; + } + } + else if( iRegionType == CANCEL_REGION ) + { + fShowMapScreenMovementList = FALSE; + return; + } + else + { + AssertMsg( 0, String( "MoveMenuBtnCallback: Invalid regionType %d, moveBoxLine %d", iRegionType, iMoveBoxLine ) ); + return; + } + + fRebuildMoveBox = TRUE; + fTeamPanelDirty = TRUE; + fMapPanelDirty = TRUE; + fCharacterInfoPanelDirty = TRUE; + MarkAllBoxesAsAltered( ); + } + } + + return; +} + + + +BOOLEAN CanMoveBoxSoldierMoveStrategically( SOLDIERTYPE *pSoldier, BOOLEAN fShowErrorMessage ) +{ + INT8 bErrorNumber = -1; + + // valid soldier? + Assert( pSoldier ); + Assert( pSoldier->bActive ); + + + if( CanCharacterMoveInStrategic( pSoldier, &bErrorNumber ) ) + { + return( TRUE ); + } + else + { + // function may fail without returning any specific error # (-1). + // if it gave us the # of an error msg, and we were told to display it + if ( ( bErrorNumber != -1 ) && fShowErrorMessage ) + { + ReportMapScreenMovementError( bErrorNumber ); + } + + return( FALSE ); + } +} + + + +void SelectAllOtherSoldiersInList( void ) +{ + INT32 iCounter = 0; + BOOLEAN fSomeCantMove = FALSE; + + + for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ ) + { + if( ( pSoldierMovingList[ iCounter ] ->bAssignment >= ON_DUTY ) && ( pSoldierMovingList[ iCounter ] ->bAssignment != VEHICLE ) ) + { + if ( CanMoveBoxSoldierMoveStrategically( pSoldierMovingList[ iCounter ], FALSE ) ) + { + fSoldierIsMoving[ iCounter ] = TRUE; + } + else + { + fSomeCantMove = TRUE; + } + } + } + + if ( fSomeCantMove ) + { + // can't - some of the OTHER soldiers can't move + ReportMapScreenMovementError( 46 ); + } +} + + + +void DeselectAllOtherSoldiersInList( void ) +{ + INT32 iCounter = 0; + + for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ ) + { + if( ( pSoldierMovingList[ iCounter ] ->bAssignment >= ON_DUTY ) && ( pSoldierMovingList[ iCounter ] ->bAssignment != VEHICLE ) ) + { + fSoldierIsMoving[ iCounter ] = FALSE; + } + } +} + + + +void HandleMoveoutOfSectorMovementTroops( void ) +{ + INT32 iCounter = 0; + SOLDIERTYPE *pSoldier = 0; + INT32 iSquadNumber = -1; + BOOLEAN fCheckForCompatibleSquad = FALSE; + + + // cancel move box + fShowMapScreenMovementList = FALSE; + + + for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ ) + { + pSoldier = pSoldierMovingList[ iCounter ]; + + fCheckForCompatibleSquad = FALSE; + + // if he is on a valid squad + if( pSoldier->bAssignment < ON_DUTY ) + { + // if he and his squad are parting ways (soldier is staying behind, but squad is leaving, or vice versa) + if( fSoldierIsMoving[ iCounter ] != IsSquadSelectedForMovement( pSoldier->bAssignment ) ) + { + // split the guy from his squad to any other compatible squad + fCheckForCompatibleSquad = TRUE; + } + } + // if in a vehicle + else if( pSoldier->bAssignment == VEHICLE ) + { + // if he and his vehicle are parting ways (soldier is staying behind, but vehicle is leaving, or vice versa) + if( fSoldierIsMoving[ iCounter ] != IsVehicleSelectedForMovement( pSoldier->iVehicleId ) ) + { + // split the guy from his vehicle to any other compatible squad + fCheckForCompatibleSquad = TRUE; + } + } + else // on his own - not on a squad or in a vehicle + { + // if he's going anywhere + if( fSoldierIsMoving[ iCounter ] ) + { + // find out if anyone is going with this guy...see if he can tag along + fCheckForCompatibleSquad = TRUE; + } + } + + + if ( fCheckForCompatibleSquad ) + { + // look for a squad that's doing the same thing as this guy is and has room for him + iSquadNumber = FindSquadThatSoldierCanJoin( pSoldier ); + if( iSquadNumber != -1 ) + { + if ( !AddCharacterToSquad( pSoldier, ( INT8 )( iSquadNumber ) ) ) + { + AssertMsg( 0, String( "HandleMoveoutOfSectorMovementTroops: AddCharacterToSquad %d failed, iCounter %d", iSquadNumber, iCounter ) ); + // toggle whether he's going or not to try and recover somewhat gracefully + fSoldierIsMoving[ iCounter ] = !fSoldierIsMoving[ iCounter ]; + } + } + else + { + // no existing squad is compatible, will have to start his own new squad + iSquadNumber = AddCharacterToUniqueSquad( pSoldier ); + if ( iSquadNumber != -1 ) + { + // It worked. Add his new squad to the "moving squads" list so others can join it, too! + AddSquadToMovingLists( iSquadNumber ); + + // If this guy is moving + if( fSoldierIsMoving[ iCounter ] ) + { + // mark this new squad as moving too, so those moving can join it + SelectSquadForMovement( iSquadNumber ); + } + } + else + { + // failed - should never happen! + AssertMsg( 0, String( "HandleMoveoutOfSectorMovementTroops: AddCharacterToUniqueSquad failed, iCounter %d", iCounter ) ); + // toggle whether he's going or not to try and recover somewhat gracefully + fSoldierIsMoving[ iCounter ] = !fSoldierIsMoving[ iCounter ]; + } + } + } + + } + + // now actually set the list + HandleSettingTheSelectedListOfMercs( ); + + return; +} + + +void HandleSettingTheSelectedListOfMercs( void ) +{ + BOOLEAN fFirstOne = TRUE; + INT32 iCounter = 0; + SOLDIERTYPE *pSoldier = NULL; + BOOLEAN fSelected; + + + // reset the selected character + bSelectedDestChar = -1; + + // run through the list of grunts + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + // is the current guy a valid character? + if( gCharactersList[ iCounter ].fValid == TRUE ) + { + pSoldier = MercPtrs[ gCharactersList[ iCounter ].usSolID ]; + + if ( pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) + { + fSelected = IsVehicleSelectedForMovement( pSoldier->bVehicleID ); + } + else + { + fSelected = IsSoldierSelectedForMovement( pSoldier ); + } + + // is he/she selected for movement? + if( fSelected ) + { + // yes, are they the first one to be selected? + if( fFirstOne == TRUE ) + { + // yes, then set them as the destination plotting character for movement arrow purposes + fFirstOne = FALSE; + + bSelectedDestChar = ( INT8 )iCounter; + // make DEST column glow + giDestHighLine = iCounter; + + ChangeSelectedInfoChar( ( INT8 ) iCounter, TRUE ); + } + + // add this guy to the selected list of grunts + SetEntryInSelectedCharacterList( ( INT8 )iCounter ); + } + } + } + + if( bSelectedDestChar != -1 ) + { + // set cursor + SetUpCursorForStrategicMap( ); + fTeamPanelDirty = TRUE; + fMapPanelDirty = TRUE; + fCharacterInfoPanelDirty = TRUE; + + DeselectSelectedListMercsWhoCantMoveWithThisGuy( &( Menptr[ gCharactersList[ bSelectedDestChar ].usSolID ] ) ); + + // remember the current paths for all selected characters so we can restore them if need be + RememberPreviousPathForAllSelectedChars(); + } +} + + +/* +INT32 GetSquadListIndexForSquadNumber( INT32 iSquadNumber ) +{ + INT32 iCounter = 0; + + for( iCounter = 0; iCounter < giNumberOfSquadsInSectorMoving; iCounter++ ) + { + if( iSquadMovingList[ iCounter ] == iSquadNumber ) + { + return( iCounter ); + } + } + + return( -1 ); +} +*/ + + +BOOLEAN AllOtherSoldiersInListAreSelected( void ) +{ + INT32 iCounter = 0, iCount = 0; + + for( iCounter = 0; iCounter < giNumberOfSoldiersInSectorMoving; iCounter++ ) + { + if( ( pSoldierMovingList[ iCounter ]->bAssignment >= ON_DUTY ) && ( pSoldierMovingList[ iCounter ]->bAssignment >= VEHICLE ) ) + { + if( fSoldierIsMoving[ iCounter ] == FALSE ) + { + return( FALSE ); + } + + iCount++; + } + } + + // some merc on other assignments and no result? + if( iCount ) + { + return( TRUE ); + } + + return( FALSE ); +} + + +BOOLEAN IsThisSquadInThisSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, INT8 bSquadValue ) +{ + INT16 sX = 0, sY = 0; + INT8 bZ = 0; + + // check if the squad is empty + if( SquadIsEmpty( bSquadValue ) == FALSE ) + { + // now grab the squad location + GetLocationOfSquad( &sX, &sY, &bZ, bSquadValue ); + + // check if this non-empty squad is in this sector + if( ( sX == sSectorX ) && ( sY == sSectorY ) && ( bSectorZ == bZ ) ) + { + // a squad that's between sectors isn't *in* this sector + if( !IsThisSquadOnTheMove( bSquadValue ) ) + { + // yep + return( TRUE ); + } + } + } + + // nope + return( FALSE ); +} + + +INT8 FindSquadThatSoldierCanJoin( SOLDIERTYPE *pSoldier ) +{ + // look for a squad that isn't full that can take this character + INT8 bCounter = 0; + + // run through the list of squads + for( bCounter = 0; bCounter < NUMBER_OF_SQUADS; bCounter++ ) + { + // is this squad in this sector + if( IsThisSquadInThisSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ, bCounter ) ) + { + // does it have room? + if( IsThisSquadFull( bCounter ) == FALSE ) + { + // is it doing the same thing as the soldier is (staying or going) ? + if( IsSquadSelectedForMovement( bCounter ) == IsSoldierSelectedForMovement( pSoldier ) ) + { + // go ourselves a match, then + return( bCounter ); + } + } + } + } + + return( -1 ); +} + +void ReBuildMoveBox( void ) +{ + // check to see if we need to rebuild the movement box and mouse regions + if( fRebuildMoveBox == FALSE ) + { + return; + } + + // reset the fact + fRebuildMoveBox = FALSE; + fTeamPanelDirty = TRUE; + fMapPanelDirty = TRUE; + fCharacterInfoPanelDirty = TRUE; + + // stop showing the box + fShowMapScreenMovementList = FALSE; + CreateDestroyMovementBox( sSelMapX, sSelMapY, ( INT16 )iCurrentMapSectorZ ); + + // show the box + fShowMapScreenMovementList = TRUE; + CreateDestroyMovementBox( sSelMapX, sSelMapY, ( INT16 )iCurrentMapSectorZ ); + ShowBox( ghMoveBox ); + MarkAllBoxesAsAltered( ); +} + + +void CreateScreenMaskForMoveBox( void ) +{ + if( fScreenMaskForMoveCreated == FALSE ) + { + // set up the screen mask + MSYS_DefineRegion( &gMoveBoxScreenMask, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_HIGHEST - 4, + MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MoveScreenMaskBtnCallback ); + + fScreenMaskForMoveCreated = TRUE; + } +} + +void RemoveScreenMaskForMoveBox( void ) +{ + if( fScreenMaskForMoveCreated == TRUE ) + { + // remove the screen mask + MSYS_RemoveRegion( &gMoveBoxScreenMask ); + fScreenMaskForMoveCreated = FALSE; + } +} + + +void MoveScreenMaskBtnCallback(MOUSE_REGION * pRegion, INT32 iReason ) +{ + // btn callback handler for move box screen mask region + if( ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP ) ) + { + fShowMapScreenMovementList = FALSE; + } + else if( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP ) + { + sSelectedMilitiaTown = 0; + + // are we showing the update box + if( fShowUpdateBox ) + { + fShowUpdateBox = FALSE; + } + } + + return; +} + +void ResetSoldierUpdateBox( void ) +{ + INT32 iCounter = 0; + + // delete any loaded faces + for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ ) + { + if( pUpdateSoldierBox[ iCounter ] != NULL ) + { + DeleteVideoObjectFromIndex( giUpdateSoldierFaces[ iCounter ] ); + } + } + + if( giMercPanelImage != 0 ) + { + DeleteVideoObjectFromIndex( giMercPanelImage ); + } + + // reset the soldier ptrs in the update box + for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ ) + { + pUpdateSoldierBox[ iCounter ] = NULL; + } + + + return; +} + + +INT32 GetNumberOfMercsInUpdateList( void ) +{ + INT32 iCounter = 0, iCount = 0; + + // run through the non-empty slots + for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ ) + { + // valid guy here + if( pUpdateSoldierBox[ iCounter ] != NULL ) + { + iCount++; + } + } + + return( iCount ); +} + +BOOLEAN IsThePopUpBoxEmpty( void ) +{ + INT32 iCounter = 0; + BOOLEAN fEmpty = TRUE; + + // run through the non-empty slots + for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ ) + { + // valid guy here + if( pUpdateSoldierBox[ iCounter ] != NULL ) + { + fEmpty = FALSE; + } + } + + return( fEmpty ); +} + + +void AddSoldierToWaitingListQueue( SOLDIERTYPE *pSoldier ) +{ + INT32 iSoldierId = 0; + + + // get soldier profile + iSoldierId = pSoldier->ubID; + + SpecialCharacterDialogueEvent( DIALOGUE_ADD_EVENT_FOR_SOLDIER_UPDATE_BOX, UPDATE_BOX_REASON_ADDSOLDIER, iSoldierId, 0, 0, 0 ); + return; +} + + +void AddReasonToWaitingListQueue( INT32 iReason ) +{ + SpecialCharacterDialogueEvent( DIALOGUE_ADD_EVENT_FOR_SOLDIER_UPDATE_BOX, UPDATE_BOX_REASON_SET_REASON, iReason, 0, 0, 0 ); + return; +} + + +void AddDisplayBoxToWaitingQueue( void ) +{ + SpecialCharacterDialogueEvent( DIALOGUE_ADD_EVENT_FOR_SOLDIER_UPDATE_BOX, UPDATE_BOX_REASON_SHOW_BOX, 0, 0, 0, 0 ); + + + return; +} + + +void ShowUpdateBox( void ) +{ + // we want to show the box + fShowUpdateBox = TRUE; +} + +void AddSoldierToUpdateBox( SOLDIERTYPE *pSoldier ) +{ + INT32 iCounter = 0; + VOBJECT_DESC VObjectDesc; + + + + // going to load face + VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; + + if( pSoldier->bLife == 0 ) + { + return; + } + + if( pSoldier -> bActive == FALSE ) + { + return; + } + + // if update + if( pUpdateSoldierBox[ iCounter ] == NULL ) + { + sprintf( VObjectDesc.ImageFile, "Interface\\panels.sti" ); + if( !AddVideoObject( &VObjectDesc, (UINT32 *)&giMercPanelImage ) ) + { + AssertMsg( 0, "Failed to load Interface\\panels.sti" ); + } + } + + // run thought list of update soldiers + for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ ) + { + // find a free slot + if( pUpdateSoldierBox[ iCounter ] == NULL ) + { + // add to box + pUpdateSoldierBox[ iCounter ] = pSoldier; + + if( gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex < 100 ) + { + // grab filename of face + sprintf( VObjectDesc.ImageFile, "Faces\\65Face\\%02d.sti", gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex ); + } + else + { + // grab filename of face + sprintf( VObjectDesc.ImageFile, "Faces\\65Face\\%03d.sti", gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex ); + } + + // load the face + AddVideoObject( &VObjectDesc, (UINT32 *)&giUpdateSoldierFaces[ iCounter ] ); + + return; + } + } + return; +} + +void SetSoldierUpdateBoxReason( INT32 iReason ) +{ + //set the reason for the update + iReasonForSoldierUpDate = iReason; + + return; +} + + +void DisplaySoldierUpdateBox( ) +{ + INT32 iNumberOfMercsOnUpdatePanel = 0; + INT32 iNumberHigh = 0, iNumberWide = 0; + INT32 iUpdatePanelWidth = 0, iUpdatePanelHeight = 0; + INT32 iX = 0, iY = 0; + INT32 iFaceX = 0, iFaceY = 0; + BOOLEAN fFourWideMode = FALSE; + HVOBJECT hBackGroundHandle; + INT32 iCounter = 0; + CHAR16 sString[ 32 ]; + INT16 sX = 0, sY = 0; + INT32 iHeightOfString = 0; + INT32 iCounterB = 0; + INT32 iOrigNumberHigh = 0, iOrigY = 0; + INT32 iUpperLimit = 0; + + + if( fShowUpdateBox == FALSE ) + { + return; + } + + + // get the number of mercs + iNumberOfMercsOnUpdatePanel = GetNumberOfMercsInUpdateList( ); + + if( iNumberOfMercsOnUpdatePanel == 0 ) + { + // nobody home + fShowUpdateBox = FALSE; + // unpause + UnPauseDialogueQueue( ); + return; + } + + giSleepHighLine = -1; + giDestHighLine = -1; + giContractHighLine = -1; + giAssignHighLine = -1; + + + //InterruptTime(); + PauseGame( ); + LockPauseState( 4 ); + + PauseDialogueQueue( ); + + // do we have enough for 4 wide, or just 2 wide? + if( iNumberOfMercsOnUpdatePanel > NUMBER_OF_MERCS_FOR_FOUR_WIDTH_UPDATE_PANEL ) + { + fFourWideMode = TRUE; + } + + // get number of rows + iNumberHigh = ( fFourWideMode ? iNumberOfMercsOnUpdatePanel / NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE + : iNumberOfMercsOnUpdatePanel / NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE); + + //number of columns + iNumberWide = ( fFourWideMode ? NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE + : NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE ); + + + + // get the height and width of the box .. will need to add in stuff for borders, lower panel...etc + if( fFourWideMode ) + { + // do we need an extra row for left overs + if( iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE ) + { + iNumberHigh++; + } + } + else + { + // do we need an extra row for left overs + if( iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE ) + { + iNumberHigh++; + } + } + + // round off + if( fFourWideMode ) + { + if(iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE ) + { + iNumberOfMercsOnUpdatePanel += NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE - ( iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE ); + } + } + else + { + if(iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE ) + { + iNumberOfMercsOnUpdatePanel += NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE - ( iNumberOfMercsOnUpdatePanel % NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE ); + } + } + + iUpdatePanelWidth = iNumberWide * TACT_WIDTH_OF_UPDATE_PANEL_BLOCKS; + + iUpdatePanelHeight = ( iNumberHigh + 1 ) * TACT_HEIGHT_OF_UPDATE_PANEL_BLOCKS; + + // WANNE 2 + iX = (MAP_BORDER_X + ((SCREEN_WIDTH - MAP_BORDER_X) / 2)) - (iUpdatePanelWidth / 2); + iY = (MAP_BORDER_Y + ((SCREEN_HEIGHT - 121) / 2)) - (iUpdatePanelHeight / 2); + + GetVideoObject( &hBackGroundHandle, guiUpdatePanelTactical ); + + //Display the 2 TOP corner pieces + BltVideoObject( guiSAVEBUFFER, hBackGroundHandle, 0, iX-4, iY - 4 , VO_BLT_SRCTRANSPARENCY,NULL ); + BltVideoObject( guiSAVEBUFFER, hBackGroundHandle, 2, iX+iUpdatePanelWidth, iY - 4 , VO_BLT_SRCTRANSPARENCY,NULL ); + + if( fFourWideMode ) + { + //Display 2 vertical lines starting at the bottom + BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 3, iX - 4, iY + iUpdatePanelHeight - 3 - 70, VO_BLT_SRCTRANSPARENCY,NULL ); + BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 5, iX + iUpdatePanelWidth, iY + iUpdatePanelHeight - 3 - 70, VO_BLT_SRCTRANSPARENCY,NULL ); + + //Display the 2 bottom corner pieces + BltVideoObject( guiSAVEBUFFER, hBackGroundHandle, 0, iX-4, iY + iUpdatePanelHeight - 3, VO_BLT_SRCTRANSPARENCY,NULL ); + BltVideoObject( guiSAVEBUFFER, hBackGroundHandle, 2, iX+iUpdatePanelWidth, iY + iUpdatePanelHeight - 3, VO_BLT_SRCTRANSPARENCY,NULL ); + } + + + SetFontDestBuffer( guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); + + iUpperLimit = fFourWideMode ? ( iNumberOfMercsOnUpdatePanel + NUMBER_OF_MERC_COLUMNS_FOR_FOUR_WIDE_MODE ) : ( iNumberOfMercsOnUpdatePanel + NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE ); + + //need to put the background down first + for( iCounter = 0; iCounter < iUpperLimit; iCounter++ ) + { + // blt the face and name + + // get the face x and y + iFaceX = iX + ( iCounter % iNumberWide ) * TACT_UPDATE_MERC_FACE_X_WIDTH; + iFaceY = iY + ( iCounter / iNumberWide ) * TACT_UPDATE_MERC_FACE_X_HEIGHT; + + BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 20, iFaceX, iFaceY , VO_BLT_SRCTRANSPARENCY,NULL ); + } + + //loop through the mercs to be displayed + for( iCounter = 0; iCounter < ( iNumberOfMercsOnUpdatePanel <= NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE ? NUMBER_OF_MERC_COLUMNS_FOR_TWO_WIDE_MODE : iNumberOfMercsOnUpdatePanel ); iCounter++ ) + { + // + // blt the face and name + // + + // get the face x and y + iFaceX = iX + ( iCounter % iNumberWide ) * TACT_UPDATE_MERC_FACE_X_WIDTH; + iFaceY = iY + ( iCounter / iNumberWide ) * TACT_UPDATE_MERC_FACE_X_HEIGHT + REASON_FOR_SOLDIER_UPDATE_OFFSET_Y; + + // now get the face + if( pUpdateSoldierBox[ iCounter ] ) + { + iFaceX += TACT_UPDATE_MERC_FACE_X_OFFSET; + iFaceY += TACT_UPDATE_MERC_FACE_Y_OFFSET; + + // there is a face + RenderSoldierSmallFaceForUpdatePanel( iCounter, iFaceX, iFaceY ); + + // display the mercs name + swprintf( sString, L"%s", pUpdateSoldierBox[ iCounter ]->name ); + DrawTextToScreen( sString, (UINT16)(iFaceX-5), (UINT16)(iFaceY + 31), 57, TINYFONT1, FONT_LTRED, FONT_BLACK, 0, CENTER_JUSTIFIED ); + } + } + + // the button container box + if( fFourWideMode ) + { + //def: 3/1/99 WAS SUBINDEX 6, + BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 19, iX - 4 + TACT_UPDATE_MERC_FACE_X_WIDTH, iY + iNumberHigh * TACT_UPDATE_MERC_FACE_X_HEIGHT + REASON_FOR_SOLDIER_UPDATE_OFFSET_Y+3, VO_BLT_SRCTRANSPARENCY,NULL ); + + // ATE: Display string for time compression + DisplayWrappedString( ( UINT16 )( iX ), ( UINT16 )( iY + iNumberHigh * TACT_UPDATE_MERC_FACE_X_HEIGHT + 5 + REASON_FOR_SOLDIER_UPDATE_OFFSET_Y + 3), ( UINT16 )( iUpdatePanelWidth ), 0, MAP_SCREEN_FONT, FONT_WHITE, gzLateLocalizedString[49], FONT_BLACK, 0, CENTER_JUSTIFIED ); + } + else + { + //def: 3/1/99 WAS SUBINDEX 6, + BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 19, iX - 4 , iY + iNumberHigh * TACT_UPDATE_MERC_FACE_X_HEIGHT + REASON_FOR_SOLDIER_UPDATE_OFFSET_Y+3, VO_BLT_SRCTRANSPARENCY,NULL ); + + // ATE: Display string for time compression + DisplayWrappedString( ( UINT16 )( iX ), ( UINT16 )( iY + iNumberHigh * TACT_UPDATE_MERC_FACE_X_HEIGHT + 5 + REASON_FOR_SOLDIER_UPDATE_OFFSET_Y+3 ), ( UINT16 )( iUpdatePanelWidth ), 0, MAP_SCREEN_FONT, FONT_WHITE, gzLateLocalizedString[49], FONT_BLACK, 0, CENTER_JUSTIFIED ); + } + + iCounter = 0; + + // now wrap the border + for( iCounter = 0; iCounter < iNumberHigh ; iCounter++ ) + { + // the sides + BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 3, iX - 4, iY + ( iCounter ) * TACT_UPDATE_MERC_FACE_X_HEIGHT, VO_BLT_SRCTRANSPARENCY,NULL ); + BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 5, iX + iUpdatePanelWidth, iY + ( iCounter ) * TACT_UPDATE_MERC_FACE_X_HEIGHT, VO_BLT_SRCTRANSPARENCY,NULL ); + } + + //big horizontal line + for( iCounter = 0; iCounter < iNumberWide; iCounter++ ) + { + // the top bottom + BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 1, iX + TACT_UPDATE_MERC_FACE_X_WIDTH * (iCounter ) , iY - 4 , VO_BLT_SRCTRANSPARENCY,NULL ); + BltVideoObject( guiSAVEBUFFER , hBackGroundHandle, 1, iX + TACT_UPDATE_MERC_FACE_X_WIDTH * (iCounter ) , iY + iUpdatePanelHeight - 3 , VO_BLT_SRCTRANSPARENCY,NULL ); + } + + + // WANNE 2 + //Display the reason for the update box + if( fFourWideMode ) + { + DisplayWrappedString( ( INT16 )( iX ), ( INT16 )( iY + 6 ), (INT16)iUpdatePanelWidth, 0, MAP_SCREEN_FONT, FONT_WHITE, pUpdateMercStrings[ iReasonForSoldierUpDate ], FONT_BLACK, 0, CENTER_JUSTIFIED ); + } + else + { + DisplayWrappedString( ( INT16 )( iX ), ( INT16 )( iY + 3 ), (INT16)iUpdatePanelWidth, 0, MAP_SCREEN_FONT, FONT_WHITE, pUpdateMercStrings[ iReasonForSoldierUpDate ], FONT_BLACK, 0, CENTER_JUSTIFIED ); + } + + + SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); + + // restore extern background rect + RestoreExternBackgroundRect( ( INT16 )( iX - 5 ), ( INT16 )( iY - 5 ), ( INT16 )( iUpdatePanelWidth + 10 ), ( INT16 )(iUpdatePanelHeight + 6 ) ); + + CreateDestroyUpdatePanelButtons( iX, ( iY + iUpdatePanelHeight - 18 ), fFourWideMode ); + MarkAButtonDirty( guiUpdatePanelButtons[ 0 ] ); + MarkAButtonDirty( guiUpdatePanelButtons[ 1 ] ); + return; +} + + +// WANNE 2 +void CreateDestroyUpdatePanelButtons(INT32 iX, INT32 iY, BOOLEAN fFourWideMode ) +{ + static BOOLEAN fCreated = FALSE; + + if( ( fShowUpdateBox == TRUE ) && ( fCreated == FALSE ) ) + { + // set to created + fCreated = TRUE; + + fShowAssignmentMenu = FALSE; + fShowContractMenu = FALSE; + +// guiUpdatePanelButtonsImage[ 0 ]= LoadButtonImage( "INTERFACE\\group_confirm.sti" ,-1,7,-1,8,-1 ); +// guiUpdatePanelButtonsImage[ 1 ] = LoadButtonImage( "INTERFACE\\group_confirm.sti" ,-1,7,-1,8,-1 ); + guiUpdatePanelButtonsImage[ 0 ]= LoadButtonImage( "INTERFACE\\group_confirm_tactical.sti" ,-1,7,-1,8,-1 ); + guiUpdatePanelButtonsImage[ 1 ] = LoadButtonImage( "INTERFACE\\group_confirm_tactical.sti" ,-1,7,-1,8,-1 ); + + if( fFourWideMode ) + { + guiUpdatePanelButtons[ 0 ] = QuickCreateButton( guiUpdatePanelButtonsImage[ 0 ], ( INT16 )( iX - 4 + TACT_UPDATE_MERC_FACE_X_WIDTH + 4), (INT16)iY, + BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, + (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)ContinueUpdateButtonCallback ); + + guiUpdatePanelButtons[ 1 ] = QuickCreateButton( guiUpdatePanelButtonsImage[ 1 ], ( INT16 ) ( iX - 4 + 2 * TACT_UPDATE_MERC_FACE_X_WIDTH + 4 ), (INT16)iY, + BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, + (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)StopUpdateButtonCallback); + } + else + { + guiUpdatePanelButtons[ 0 ] = QuickCreateButton( guiUpdatePanelButtonsImage[ 0 ], ( INT16 )( iX), (INT16)iY, + BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST -1, + (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)ContinueUpdateButtonCallback); + + guiUpdatePanelButtons[ 1 ] = QuickCreateButton( guiUpdatePanelButtonsImage[ 1 ], ( INT16 )( iX + TACT_UPDATE_MERC_FACE_X_WIDTH ), (INT16)iY, + BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, + (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)StopUpdateButtonCallback); + + } + + SpecifyButtonText( guiUpdatePanelButtons[ 0 ], pUpdatePanelButtons[ 0 ] ); + SpecifyButtonFont( guiUpdatePanelButtons[ 0 ], MAP_SCREEN_FONT ); + SpecifyButtonUpTextColors( guiUpdatePanelButtons[ 0 ], FONT_MCOLOR_BLACK, FONT_BLACK ); + SpecifyButtonDownTextColors( guiUpdatePanelButtons[ 0 ], FONT_MCOLOR_BLACK, FONT_BLACK ); + SetButtonFastHelpText( guiUpdatePanelButtons[ 0 ], gzLateLocalizedString[51] ); + + SpecifyButtonText( guiUpdatePanelButtons[ 1 ], pUpdatePanelButtons[ 1 ] ); + SpecifyButtonFont( guiUpdatePanelButtons[ 1 ], MAP_SCREEN_FONT ); + SpecifyButtonUpTextColors( guiUpdatePanelButtons[ 1 ], FONT_MCOLOR_BLACK, FONT_BLACK ); + SpecifyButtonDownTextColors( guiUpdatePanelButtons[ 1 ], FONT_MCOLOR_BLACK, FONT_BLACK ); + SetButtonFastHelpText( guiUpdatePanelButtons[ 1 ], gzLateLocalizedString[52] ); + } + else if( ( fShowUpdateBox == FALSE ) && ( fCreated == TRUE ) ) + { + // set to uncreated + fCreated = FALSE; + + // get rid of the buttons and images + RemoveButton( guiUpdatePanelButtons[ 0 ] ); + RemoveButton( guiUpdatePanelButtons[ 1 ] ); + + UnloadButtonImage( guiUpdatePanelButtonsImage[ 0 ]); + UnloadButtonImage( guiUpdatePanelButtonsImage[ 1 ]); + + // unpause + UnPauseDialogueQueue( ); + } +} + + +/* +void CreateUpdateBox( void ) +{ + // create basic box + CreatePopUpBox(&ghUpdateBox, AssignmentDimensions, MovePosition, (POPUP_BOX_FLAG_CLIP_TEXT|POPUP_BOX_FLAG_RESIZE )); + + // which buffer will box render to + SetBoxBuffer(ghUpdateBox, FRAME_BUFFER); + + // border type? + SetBorderType(ghUpdateBox,guiPOPUPBORDERS); + + // background texture + SetBackGroundSurface(ghUpdateBox, guiPOPUPTEX); + + // margin sizes + SetMargins( ghUpdateBox, 6, 6, 4, 4 ); + + // space between lines + SetLineSpace(ghUpdateBox, 2); + + // set current box to this one + SetCurrentBox( ghUpdateBox ); + + // add strings + CreateUpdateBoxStrings( ); + + // set font type + SetBoxFont(ghUpdateBox, MAP_SCREEN_FONT); + + // set highlight color + SetBoxHighLight(ghUpdateBox, FONT_WHITE); + + // unhighlighted color + SetBoxForeground(ghUpdateBox, FONT_LTGREEN); + + // background color + SetBoxBackground(ghUpdateBox, FONT_BLACK); + + // shaded color..for darkened text + SetBoxShade( ghUpdateBox, FONT_BLACK ); + + // resize box to text + ResizeBoxToText( ghUpdateBox ); + + // create screen mask + CreateScreenMaskForMoveBox( ); + + ShowBox( ghUpdateBox ); + + return; +} + + +void CreateUpdateBoxStrings( void ) +{ + INT32 iCounter = 0; + CHAR16 sString[ 64 ]; + INT32 hStringHandle; + + swprintf( sString, L"%s", pUpdateMercStrings[ iReasonForSoldierUpDate ] ); + AddMonoString(&hStringHandle, sString ); + + for( iCounter = 0; iCounter < SIZE_OF_UPDATE_BOX; iCounter++ ) + { + // find valid soldier, add name + if( pUpdateSoldierBox[ iCounter ] ) + { + swprintf( sString, L"%s", pUpdateSoldierBox[ iCounter ]->name ); + AddMonoString(&hStringHandle, sString ); + } + } + + // add a few blank lines + sString[ 0 ] = 0; + + AddMonoString(&hStringHandle, sString ); + AddMonoString(&hStringHandle, sString ); + AddMonoString(&hStringHandle, sString ); + AddMonoString(&hStringHandle, sString ); +} + + + +void RemoveUpdateBox( void ) +{ + // remove the box + RemoveBox( ghUpdateBox ); + ghUpdateBox = -1; + + iReasonForSoldierUpDate = NO_REASON_FOR_UPDATE; + + // remove the screen mask + RemoveScreenMaskForMoveBox( ); + + // reset mercs that are in progress of being updated + ResetSoldierUpdateBox( ); +} + + + +void DisplayUpdateBox( void ) +{ + if( fShowUpdateBox ) + { + // show the box + ShowBox( ghUpdateBox ); + PauseTime( TRUE ); + } + return; +} +*/ + + + +void CreateDestroyTheUpdateBox( void ) +{ + static BOOLEAN fCreated = FALSE; + + if( ( fCreated == FALSE ) && ( fShowUpdateBox == TRUE ) ) + { + + if( GetNumberOfMercsInUpdateList( ) == 0 ) + { + fShowUpdateBox = FALSE; + return; + } + + fCreated = TRUE; + + //InterruptTime(); + // create screen mask + CreateScreenMaskForMoveBox( ); + + // lock it paused + PauseGame( /*TRUE*/ ); // doesn't take parameters (jonathanl) + LockPauseState( 5 ); + + // display the box + DisplaySoldierUpdateBox( ); + + // Do beep + PlayJA2SampleFromFile( "Sounds\\newbeep.wav", RATE_11025, MIDVOLUME, 1 , MIDDLEPAN ); + } + else if( ( fCreated == TRUE ) && ( fShowUpdateBox == FALSE ) ) + { + fCreated = FALSE; + + UnLockPauseState( ); + UnPauseGame( /*FALSE*/ ); // doesn't take parameters (jonathanl) + + // dirty screen + fMapPanelDirty = TRUE; + fTeamPanelDirty = TRUE; + fCharacterInfoPanelDirty = TRUE; + + // remove screen mask + RemoveScreenMaskForMoveBox( ); + + ResetSoldierUpdateBox( ); + + CreateDestroyUpdatePanelButtons( 0, 0, FALSE ); + } +} + + +void UpdateButtonsDuringCharacterDialoguePicture( void ) +{ + // stop showing buttons during certain instances of dialogue + if ( (guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) ) + { + UnMarkButtonDirty( giCharInfoButton[ 0 ] ); + UnMarkButtonDirty( giCharInfoButton[ 1 ] ); + } + +} + +void UpdateButtonsDuringCharacterDialogueSubTitles( void ) +{ + if( (guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) && ( gGameSettings.fOptions[ TOPTION_SUBTITLES ] ) ) + { + UnMarkButtonDirty( giMapContractButton ); + } + + return; +} + + +void RenderSoldierSmallFaceForUpdatePanel( INT32 iIndex, INT32 iX, INT32 iY ) +{ + INT32 iStartY = 0; + SOLDIERTYPE *pSoldier = NULL; + + // fill the background for the info bars black + ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iY+2, iX+44, iY+30, 0 ); + + // put down the background + BltVideoObjectFromIndex( guiSAVEBUFFER, giMercPanelImage, 0, iX, iY, VO_BLT_SRCTRANSPARENCY, NULL ); + + // grab the face + BltVideoObjectFromIndex( guiSAVEBUFFER , giUpdateSoldierFaces[ iIndex ], 0, iX+2, iY+2, VO_BLT_SRCTRANSPARENCY, NULL ); + + //HEALTH BAR + pSoldier = pUpdateSoldierBox[ iIndex ]; + + // is the merc alive? + if( !pSoldier->bLife ) + return; + + + //yellow one for bleeding + iStartY = iY + 29 - 27*pSoldier->bLifeMax/100; + ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iStartY, iX+37, iY+29, Get16BPPColor( FROMRGB( 107, 107, 57 ) ) ); + ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+37, iStartY, iX+38, iY+29, Get16BPPColor( FROMRGB( 222, 181, 115 ) ) ); + + //pink one for bandaged. + iStartY += 27*pSoldier->bBleeding/100; + ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iStartY, iX+37, iY+29, Get16BPPColor( FROMRGB( 156, 57, 57 ) ) ); + ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+37, iStartY, iX+38, iY+29, Get16BPPColor( FROMRGB( 222, 132, 132 ) ) ); + + //red one for actual health + iStartY = iY + 29 - 27*pSoldier->bLife/100; + ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+36, iStartY, iX+37, iY+29, Get16BPPColor( FROMRGB( 107, 8, 8 ) ) ); + ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+37, iStartY, iX+38, iY+29, Get16BPPColor( FROMRGB( 206, 0, 0 ) ) ); + + //BREATH BAR + iStartY = iY + 29 - 27*pSoldier->bBreathMax/100; + ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+39, iStartY, iX+40, iY+29, Get16BPPColor( FROMRGB( 8, 8, 132 ) ) ); + ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+40, iStartY, iX+41, iY+29, Get16BPPColor( FROMRGB( 8, 8, 107 ) ) ); + + //MORALE BAR + iStartY = iY + 29 - 27*pSoldier->bMorale/100; + ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+42, iStartY, iX+43, iY+29, Get16BPPColor( FROMRGB( 8, 156, 8 ) ) ); + ColorFillVideoSurfaceArea( guiSAVEBUFFER, iX+43, iStartY, iX+44, iY+29, Get16BPPColor( FROMRGB( 8, 107, 8 ) ) ); + + + return; +} + +void ContinueUpdateButtonCallback(GUI_BUTTON *btn,INT32 reason) +{ + if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) + { + btn->uiFlags|=(BUTTON_CLICKED_ON); + } + else if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP ) + { + if (btn->uiFlags & BUTTON_CLICKED_ON) + { + btn->uiFlags&=~(BUTTON_CLICKED_ON); + + EndUpdateBox( TRUE ); // restart time compression + } + } + + return; +} + + +void StopUpdateButtonCallback(GUI_BUTTON *btn,INT32 reason) +{ + if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) + { + btn->uiFlags|=(BUTTON_CLICKED_ON); + } + else if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP ) + { + if (btn->uiFlags & BUTTON_CLICKED_ON) + { + btn->uiFlags&=~(BUTTON_CLICKED_ON); + + EndUpdateBox( FALSE ); // stop time compression + } + } + + return; +} + + + +void EndUpdateBox( BOOLEAN fContinueTimeCompression ) +{ + fShowUpdateBox = FALSE; + + CreateDestroyTheUpdateBox(); + + if ( fContinueTimeCompression ) + { + StartTimeCompression(); + } + else + { + StopTimeCompression(); + } +} + + + +void SetUpdateBoxFlag( BOOLEAN fFlag ) +{ + // set the flag + fShowUpdateBox = fFlag; + return; +} + + +void SetTixaAsFound( void ) +{ + // set the town of Tixa as found by the player + fFoundTixa = TRUE; + fMapPanelDirty = TRUE; +} + +void SetOrtaAsFound( void ) +{ + // set the town of Orta as found by the player + fFoundOrta = TRUE; + fMapPanelDirty = TRUE; +} + +void SetSAMSiteAsFound( UINT8 uiSamIndex ) +{ + // set this SAM site as being found by the player + fSamSiteFound[ uiSamIndex ] = TRUE; + fMapPanelDirty = TRUE; +} + + +// ste up the timers for move menu in mapscreen for double click detection +void InitTimersForMoveMenuMouseRegions( void ) +{ + INT32 iCounter = 0; + + for( iCounter = 0; iCounter < MAX_POPUP_BOX_STRING_COUNT; iCounter++ ) + { + giDblClickTimersForMoveBoxMouseRegions[ iCounter ] = 0; + } +} + +void UpdateHelpTextForMapScreenMercIcons( void ) +{ + if( ( bSelectedInfoChar == -1 ) || ( gCharactersList[ bSelectedInfoChar ].fValid == FALSE ) ) + { + SetRegionFastHelpText( &(gContractIconRegion), L"" ); + SetRegionFastHelpText( &(gInsuranceIconRegion), L"" ); + SetRegionFastHelpText( &(gDepositIconRegion), L"" ); + } + else + { + // if merc is an AIM merc + if( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ].ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC ) + { + SetRegionFastHelpText( &(gContractIconRegion), zMarksMapScreenText[ 22 ] ); + } + else + { + SetRegionFastHelpText( &(gContractIconRegion), L"" ); + } + + // if merc has life insurance + if( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ].usLifeInsurance > 0 ) + { + SetRegionFastHelpText( &(gInsuranceIconRegion), zMarksMapScreenText[ 3 ] ); + } + else + { + SetRegionFastHelpText( &(gInsuranceIconRegion), L"" ); + } + + // if merc has a medical deposit + if( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ].usMedicalDeposit > 0 ) + { + SetRegionFastHelpText( &(gDepositIconRegion), zMarksMapScreenText[ 12 ] ); + } + else + { + SetRegionFastHelpText( &(gDepositIconRegion), L"" ); + } + } +} + +void CreateDestroyInsuranceMouseRegionForMercs( BOOLEAN fCreate ) +{ + static BOOLEAN fCreated = FALSE; + + if( ( fCreated == FALSE ) && ( fCreate == TRUE ) ) + { + MSYS_DefineRegion( &gContractIconRegion, CHAR_ICON_X, CHAR_ICON_CONTRACT_Y, CHAR_ICON_X + CHAR_ICON_WIDTH, CHAR_ICON_CONTRACT_Y + CHAR_ICON_HEIGHT, + MSYS_PRIORITY_HIGH - 1, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK ); + + MSYS_DefineRegion( &gInsuranceIconRegion, CHAR_ICON_X, CHAR_ICON_CONTRACT_Y + CHAR_ICON_SPACING, CHAR_ICON_X + CHAR_ICON_WIDTH, CHAR_ICON_CONTRACT_Y + CHAR_ICON_SPACING + CHAR_ICON_HEIGHT, + MSYS_PRIORITY_HIGH - 1, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK ); + + MSYS_DefineRegion( &gDepositIconRegion, CHAR_ICON_X, CHAR_ICON_CONTRACT_Y + ( 2 * CHAR_ICON_SPACING ), CHAR_ICON_X + CHAR_ICON_WIDTH, CHAR_ICON_CONTRACT_Y + ( 2 * CHAR_ICON_SPACING ) + CHAR_ICON_HEIGHT, + MSYS_PRIORITY_HIGH - 1, MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK ); + + fCreated = TRUE; + } + else if( ( fCreated == TRUE ) && ( fCreate == FALSE ) ) + { + MSYS_RemoveRegion( &gContractIconRegion ); + MSYS_RemoveRegion( &gInsuranceIconRegion ); + MSYS_RemoveRegion( &gDepositIconRegion ); + fCreated = FALSE; + } +} + + +/* +void HandlePlayerEnteringMapScreenBeforeGoingToTactical( void ) +{ + CHAR16 sString[ 256 ]; + + if( !( AnyMercsHired( ) ) ) + { + // no mercs hired inform player they must hire mercs + swprintf( sString, pMapScreenJustStartedHelpText[ 0 ] ); + DoMapMessageBox( MSG_BOX_BASIC_STYLE, sString, MAP_SCREEN, MSG_BOX_FLAG_OK, DoneHandlePlayerFirstEntryToMapScreen ); + + } + else + { + // player has mercs hired, tell them to time compress to get things underway + swprintf( sString, pMapScreenJustStartedHelpText[ 1 ] ); + fShowMapScreenHelpText = TRUE; + } + + + + // now inform the player + + if( fShowMapScreenHelpText ) + { + fShowMapScreenHelpText = FALSE; + SetUpShutDownMapScreenHelpTextScreenMask( ); + fShowMapScreenHelpText = TRUE; + } + + return; +} + + +void DoneHandlePlayerFirstEntryToMapScreen( UINT8 bExitValue ) +{ + static BOOLEAN fFirstTime = TRUE; + + if( bExitValue == MSG_BOX_RETURN_OK ) + { + if( fFirstTime == TRUE ) + { + fFirstTime = FALSE; + fShowMapScreenHelpText = TRUE; + } + } +} +*/ + + +BOOLEAN HandleTimeCompressWithTeamJackedInAndGearedToGo( void ) +{ + // check a team is ready to go + if( !( AnyMercsHired( ) ) ) + { + // no mercs, leave + return( FALSE ); + } + + // make sure the game just started + if( gTacticalStatus.fDidGameJustStart == FALSE ) + { + return( FALSE ); + } + + // select starting sector (A9 - Omerta) + ChangeSelectedMapSector( 9, 1, 0 ); + + // load starting sector + if ( !SetCurrentWorldSector( 9, 1, 0 ) ) + { + return( FALSE ); + } + + //Setup variables in the PBI for this first battle. We need to support the + //non-persistant PBI in case the user goes to mapscreen. + gfBlitBattleSectorLocator = TRUE; + gubPBSectorX = 9; + gubPBSectorY = 1; + gubPBSectorZ = 0; + gubEnemyEncounterCode = ENTERING_ENEMY_SECTOR_CODE; + + InitHelicopterEntranceByMercs( ); + + FadeInGameScreen( ); + + SetUpShutDownMapScreenHelpTextScreenMask( ); + + // Add e-mail message + AddEmail(ENRICO_CONGRATS,ENRICO_CONGRATS_LENGTH,MAIL_ENRICO, GetWorldTotalMin() ); + + + return( TRUE ); +} + +void HandleDisplayOfExitToTacticalMessageForFirstEntryToMapScreen( void ) +{ + INT32 iTime = 0, iDifference = 0; + + if( gTacticalStatus.fDidGameJustStart == FALSE ) + { + return; + } + + if( AnyMercsHired() == FALSE ) + { + return; + } + + if( fResetTimerForFirstEntryIntoMapScreen ) + { + giExitToTactBaseTime = 0; + fResetTimerForFirstEntryIntoMapScreen = FALSE; + } + + // is this the first time in? + if( giExitToTactBaseTime == 0 ) + { + // gte the clock, for initing + giExitToTactBaseTime = GetJA2Clock(); + } + + iTime = GetJA2Clock(); + + iDifference = iTime - giExitToTactBaseTime; + + if( iDifference > TIMER_FOR_SHOW_EXIT_TO_TACTICAL_MESSAGE ) + { + fShowMapScreenHelpText = FALSE; + fMapPanelDirty = TRUE; + fTeamPanelDirty = TRUE; + fCharacterInfoPanelDirty = TRUE; + giExitToTactBaseTime = 0; + } + + + return; +} + + +BOOLEAN NotifyPlayerWhenEnemyTakesControlOfImportantSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, BOOLEAN fContested ) +{ + CHAR16 sString[ 128 ], sStringA[ 64 ], sStringB[ 256 ], sStringC[ 64 ]; + INT32 iValue = 0; + INT8 bTownId = 0; + INT16 sSector = 0; + INT8 bMineIndex; + + + // are we below ground? + if( bSectorZ != 0 ) + { + // yes we are..there is nothing important to player here + return( FALSE ); + } + + // get the name of the sector + GetSectorIDString( sSectorX, sSectorY, bSectorZ, sString, TRUE ); + + bTownId = GetTownIdForSector( sSectorX, sSectorY ); + + // check if SAM site here + if( IsThisSectorASAMSector( sSectorX, sSectorY, bSectorZ ) ) + { + swprintf( sStringB, pMapErrorString[ 15 ], sString ); + + // put up the message informing the player of the event + DoScreenIndependantMessageBox( sStringB, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); + return( TRUE ); + } + + + // check if a mine is here + if( IsThereAMineInThisSector( sSectorX, sSectorY ) ) + { + bMineIndex = GetMineIndexForSector( sSectorX, sSectorY ); + + // if it was producing for us + if ( ( GetMaxDailyRemovalFromMine( bMineIndex ) > 0 ) && SpokenToHeadMiner( bMineIndex ) ) + { + // get how much we now will get from the mines + iValue = GetProjectedTotalDailyIncome( ); + + // parse the string + swprintf( sStringC, L"%d", iValue ); + + // insert + InsertCommasForDollarFigure( sStringC ); + InsertDollarSignInToString( sStringC ); + + swprintf( sStringB, pMapErrorString[ 16 ], sString, sStringC ); + + // put up the message informing the player of the event + DoScreenIndependantMessageBox( sStringB, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); + return( TRUE ); + } + } + + + if( fContested && bTownId ) + { + if( bTownId == SAN_MONA ) + { //San Mona isn't important. + return( TRUE ); + } + swprintf( sStringB, pMapErrorString[ 25 ], sString ); + + // put up the message informing the player of the event + DoScreenIndependantMessageBox( sStringB, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); + return( TRUE ); + } + + // get the strategic sector value + sSector = sSectorX + MAP_WORLD_X * sSectorY; + + if( StrategicMap[ sSector ].bNameId == BLANK_SECTOR ) + { + return( FALSE ); + } + + // get the name of the sector + GetSectorIDString( sSectorX, sSectorY, bSectorZ, sStringA, TRUE ); + + // now build the string + swprintf( sString, pMapErrorString[ 17 ], sStringA ); + + // put up the message box + DoScreenIndependantMessageBox( sString, MSG_BOX_FLAG_OK, NULL ); + + return( TRUE ); +} + + +void NotifyPlayerOfInvasionByEnemyForces( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, MSGBOX_CALLBACK ReturnCallback ) +{ + INT16 sSector = 0; + INT8 bTownId = 0; + CHAR16 sString[ 128 ], sStringA[ 128 ]; + + + // check if below ground + if( bSectorZ != 0 ) + { + return; + } + + // grab sector value + sSector = sSectorX + MAP_WORLD_X * sSectorY; + + if( StrategicMap[ sSector ].fEnemyControlled == TRUE ) + { + // enemy controlled any ways, leave + return; + } + + // get the town id + bTownId = StrategicMap[ sSector ].bNameId; + + // check if SAM site here + if( IsThisSectorASAMSector( sSectorX, sSectorY, bSectorZ ) ) + { + // get sector id value + GetShortSectorString( sSectorX, sSectorY, sStringA ); + + swprintf( sString, pMapErrorString[ 22 ], sStringA ); + DoScreenIndependantMessageBox( sString, MSG_BOX_FLAG_OK, ReturnCallback ); + } + else if( bTownId ) + { + // get the name of the sector + GetSectorIDString( sSectorX, sSectorY, bSectorZ, sStringA, TRUE ); + + swprintf( sString, pMapErrorString[ 23 ], sStringA ); + DoScreenIndependantMessageBox( sString, MSG_BOX_FLAG_OK, ReturnCallback ); + } + else + { + // get sector id value + GetShortSectorString( sSectorX, sSectorY, sStringA ); + + swprintf( sString, pMapErrorString[ 24 ], sStringA ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, sString ); + } +} + + +BOOLEAN CanCharacterMoveInStrategic( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber ) +{ + BOOLEAN fCanMove = TRUE; + INT16 sSector = 0; + BOOLEAN fProblemExists = FALSE; + + + // valid soldier? + Assert( pSoldier ); + Assert( pSoldier->bActive); + + + // NOTE: Check for the most permanent conditions first, and the most easily remedied ones last! + // In case several cases apply, only the reason found first will be given, so make it a good one! + + + // still in transit? + if( IsCharacterInTransit( pSoldier ) == TRUE ) + { + *pbErrorNumber = 8; + return( FALSE ); + } + + // a POW? + if( pSoldier->bAssignment == ASSIGNMENT_POW ) + { + *pbErrorNumber = 5; + return( FALSE ); + } + + + // underground? (can't move strategically, must use tactical traversal ) + if( pSoldier->bSectorZ != 0 ) + { + *pbErrorNumber = 1; + return( FALSE ); + } + + + // vehicle checks + if ( pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) + { + // empty (needs a driver!)? + if ( GetNumberInVehicle( pSoldier->bVehicleID ) == 0 ) + { + *pbErrorNumber = 32; + return( FALSE ); + } + + // too damaged? + if ( pSoldier->bLife < OKLIFE ) + { + *pbErrorNumber = 47; + return( FALSE ); + } + + // out of fuel? + if ( !VehicleHasFuel( pSoldier ) ) + { + *pbErrorNumber = 42; + return( FALSE ); + } + } + else // non-vehicle + { + // dead? + if ( pSoldier->bLife <= 0 ) + { + swprintf( gsCustomErrorString, pMapErrorString[ 35 ], pSoldier->name ); + *pbErrorNumber = -99; // customized error message! + return( FALSE ); + } + + // too injured? + if ( pSoldier->bLife < OKLIFE ) + { + swprintf( gsCustomErrorString, pMapErrorString[ 33 ], pSoldier->name ); + *pbErrorNumber = -99; // customized error message! + return( FALSE ); + } + } + + + // if merc is in a particular sector, not somewhere in between + if ( pSoldier->fBetweenSectors == FALSE ) + { + // and he's NOT flying above it all in a working helicopter + if( !SoldierAboardAirborneHeli( pSoldier ) ) + { + // and that sector is loaded... + if( ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && + ( pSoldier->bSectorZ == gbWorldSectorZ ) ) + { + // in combat? + if( gTacticalStatus.uiFlags & INCOMBAT ) + { + *pbErrorNumber = 11; + return( FALSE ); + } + + // hostile sector? + if ( gTacticalStatus.fEnemyInSector ) + { + *pbErrorNumber = 2; + return( FALSE ); + } + + // air raid in loaded sector where character is? + if( InAirRaid( ) ) + { + *pbErrorNumber = 10; + return( FALSE ); + } + } + + // not necessarily loaded - if there are any hostiles there + if( NumHostilesInSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ) > 0 ) + { + *pbErrorNumber = 2; + return( FALSE ); + } + } + } + + + // if in L12 museum, and the museum alarm went off, and Eldin still around? + if ( ( pSoldier->sSectorX == 12 ) && ( pSoldier->sSectorY == MAP_ROW_L ) && ( pSoldier->bSectorZ == 0 ) && + ( !pSoldier->fBetweenSectors ) && gMercProfiles[ ELDIN ].bMercStatus != MERC_IS_DEAD ) + { + UINT8 ubRoom, cnt; + SOLDIERTYPE * pSoldier2; + + if ( InARoom( pSoldier->sGridNo, &ubRoom ) && ubRoom >= 22 && ubRoom <= 41 ) + { + + cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; + + for ( pSoldier2 = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pSoldier2++) + { + if ( pSoldier2->bActive ) + { + if ( FindObj( pSoldier2, CHALICE ) != ITEM_NOT_FOUND ) + { + *pbErrorNumber = 34; + return( FALSE ); + } + } + } + } + } + + + // on assignment, other than just in a VEHICLE? + if( ( pSoldier->bAssignment >= ON_DUTY ) && ( pSoldier->bAssignment != VEHICLE ) ) + { + *pbErrorNumber = 3; + return( FALSE ); + } + + // if he's walking/driving, and so tired that he would just stop the group anyway in the next sector, + // or already asleep and can't be awakened + if ( PlayerSoldierTooTiredToTravel( pSoldier ) ) + { + // too tired + swprintf( gsCustomErrorString, pMapErrorString[ 43 ], pSoldier->name ); + *pbErrorNumber = -99; // customized error message! + return( FALSE ); + } + + + // a robot? + if ( AM_A_ROBOT( pSoldier ) ) + { + // going alone? + if ( ( ( pSoldier->bAssignment == VEHICLE ) && ( !IsRobotControllerInVehicle( pSoldier->iVehicleId ) ) ) || + ( ( pSoldier->bAssignment < ON_DUTY ) && ( !IsRobotControllerInSquad( pSoldier->bAssignment ) ) ) ) + { + *pbErrorNumber = 49; + return( FALSE ); + } + } + // an Escorted NPC? + else if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__EPC ) + { + // going alone? + if ( ( ( pSoldier->bAssignment == VEHICLE ) && ( GetNumberOfNonEPCsInVehicle( pSoldier->iVehicleId ) == 0 ) ) || + ( ( pSoldier->bAssignment < ON_DUTY ) && ( NumberOfNonEPCsInSquad( pSoldier->bAssignment ) == 0 ) ) ) + { + // are they male or female + if( gMercProfiles[ pSoldier->ubProfile ].bSex == MALE ) + { + swprintf( gsCustomErrorString, L"%s %s", pSoldier->name ,pMapErrorString[ 6 ] ); + } + else + { + swprintf( gsCustomErrorString, L"%s %s", pSoldier->name ,pMapErrorString[ 7 ] ); + } + + *pbErrorNumber = -99; // customized error message! + return( FALSE ); + } + } + + + // assume there's no problem + fProblemExists = FALSE; + + // find out if this particular character can't move for some reason + switch( pSoldier->ubProfile ) + { + case( MARIA ): + // Maria can't move if she's in sector C5 + sSector = SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ); + if( sSector == SEC_C5 ) + { + // can't move at this time + fProblemExists = TRUE; + } + break; + } + + if ( fProblemExists ) + { + // inform user this specific merc cannot be moved out of the sector + swprintf( gsCustomErrorString, pMapErrorString[ 29 ], pSoldier->name ); + *pbErrorNumber = -99; // customized error message! + return( FALSE ); + } + + + // passed all checks - this character may move strategically! + return( TRUE ); +} + + +BOOLEAN CanEntireMovementGroupMercIsInMove( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber ) +{ + SOLDIERTYPE *pCurrentSoldier = NULL; + INT32 iCounter = 0; + UINT8 ubGroup = 0; + UINT8 ubCurrentGroup = 0; + + + // first check the requested character himself + if( CanCharacterMoveInStrategic( pSoldier, pbErrorNumber ) == FALSE ) + { + // failed no point checking anyone else + return( FALSE ); + } + + + // now check anybody who would be travelling with him + + // does character have group? + if( pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) + { + // IS a vehicle - use vehicle's group + ubGroup = pVehicleList[ pSoldier->bVehicleID ].ubMovementGroup; + } + else if( pSoldier->bAssignment == VEHICLE ) + { + // IN a vehicle - use vehicle's group + ubGroup = pVehicleList[ pSoldier->iVehicleId ].ubMovementGroup; + } + else + { + ubGroup = pSoldier->ubGroupID; + } + + // even if group is 0 (not that that should happen, should it?) still loop through for other mercs selected to move + + // if anyone in the merc's group or also selected cannot move for whatever reason return false + for( iCounter = 0; iCounter < MAX_CHARACTER_COUNT; iCounter++ ) + { + if( gCharactersList[ iCounter ].fValid == TRUE ) + { + // get soldier + pCurrentSoldier = &( Menptr[ gCharactersList[ iCounter ].usSolID ] ); + + // skip inactive grunts + if( pCurrentSoldier->bActive == FALSE ) + { + continue; + } + + // skip the same guy we did already + if ( pCurrentSoldier == pSoldier ) + { + continue; + } + + // does character have group? + if( pCurrentSoldier->uiStatusFlags & SOLDIER_VEHICLE ) + { + // IS a vehicle + ubCurrentGroup = pVehicleList[ pCurrentSoldier->bVehicleID ].ubMovementGroup; + } + else if( pCurrentSoldier->bAssignment == VEHICLE ) + { + // IN a vehicle + ubCurrentGroup = pVehicleList[ pCurrentSoldier->iVehicleId ].ubMovementGroup; + } + else + { + ubCurrentGroup = pCurrentSoldier->ubGroupID; + } + + // if he is in the same movement group (i.e. squad), or he is still selected to go with us (legal?) + if( ( ubCurrentGroup == ubGroup ) || ( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE ) ) + { + // can this character also move strategically? + if( CanCharacterMoveInStrategic( pCurrentSoldier, pbErrorNumber ) == FALSE ) + { + // cannot move, fail, and don't bother checking anyone else, either + return( FALSE ); + } + } + } + } + + + // everybody can move... Yey! :-) + return( TRUE ); +} + + + +void ReportMapScreenMovementError( INT8 bErrorNumber ) +{ + if ( bErrorNumber == -99 ) + { + // - 99 is a special message # indicating a customized message + DoMapMessageBox( MSG_BOX_BASIC_STYLE, (INT16 *)gsCustomErrorString, MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); + } + else + { + DoMapMessageBox( MSG_BOX_BASIC_STYLE, (INT16 *)pMapErrorString[ bErrorNumber ], MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); + } +} + + +// we are checking to see if we need to in fact rebuild the characterlist for mapscreen +void HandleRebuildingOfMapScreenCharacterList( void ) +{ + // check if we need to rebuild the list? + if( fReBuildCharacterList ) + { + // do the actual rebuilding + ReBuildCharactersList( ); + + // reset the flag + fReBuildCharacterList = FALSE; + } +} + + +void RequestToggleTimeCompression( void ) +{ + if( !IsTimeBeingCompressed( ) ) + { + StartTimeCompression(); + } + else // currently compressing + { + StopTimeCompression(); + } +} + + +void RequestIncreaseInTimeCompression( void ) +{ + if ( IsTimeBeingCompressed( ) ) + { + IncreaseGameTimeCompressionRate(); + } + else + { +/* + // start compressing + StartTimeCompression(); +*/ + // ARM Change: start over at 5x compression + SetGameTimeCompressionLevel( TIME_COMPRESS_5MINS ); + } +} + + + +void RequestDecreaseInTimeCompression( void ) +{ + if ( IsTimeBeingCompressed( ) ) + { + DecreaseGameTimeCompressionRate(); + } + else + { + // check that we can + if ( !AllowedToTimeCompress( ) ) + { + // not allowed to compress time + TellPlayerWhyHeCantCompressTime(); + return; + } + + // ARM Change: do nothing +/* + // if compression mode is set, just restart time so player can see it + if ( giTimeCompressMode > TIME_COMPRESS_X1 ) + { + StartTimeCompression(); + } +*/ + } +} + + + +BOOLEAN CanSoldierMoveWithVehicleId( SOLDIERTYPE *pSoldier, INT32 iVehicle1Id ) +{ + INT32 iVehicle2Id = -1; + VEHICLETYPE *pVehicle1, *pVehicle2; + + + Assert( iVehicle1Id != -1 ); + + // if soldier is IN a vehicle + if( pSoldier->bAssignment == VEHICLE ) + { + iVehicle2Id = pSoldier->iVehicleId; + } + else + // if soldier IS a vehicle + if( pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) + { + iVehicle2Id = pSoldier->bVehicleID; + } + + + // if also (in) a vehicle + if ( iVehicle2Id != -1 ) + { + // if it's the same vehicle + if ( iVehicle1Id == iVehicle2Id ) + { + return( TRUE ); + } + + // helicopter can't move together with ground vehicles! + if ( ( iVehicle1Id == iHelicopterVehicleId ) || ( iVehicle2Id == iHelicopterVehicleId ) ) + { + return( FALSE ); + } + + pVehicle1 = &( pVehicleList[ iVehicle1Id ] ); + pVehicle2 = &( pVehicleList[ iVehicle2Id ] ); + + // as long as they're in the same location, amd neither is between sectors, different vehicles is also ok + if( ( pVehicle1->sSectorX == pVehicle2->sSectorX ) && + ( pVehicle1->sSectorY == pVehicle2->sSectorY ) && + ( pVehicle1->sSectorZ == pVehicle2->sSectorZ ) && + !pVehicle1->fBetweenSectors && + !pVehicle2->fBetweenSectors ) + { + return( TRUE ); + } + } + + + // not in/is a vehicle, or in a different vehicle that isn't in the same location + return ( FALSE ); +} + + +BOOLEAN SaveLeaveItemList( HWFILE hFile ) +{ + INT32 iCounter = 0; + MERC_LEAVE_ITEM *pCurrentItem; + UINT32 uiCount=0; + UINT32 uiNumBytesWritten = 0; + BOOLEAN fNodeExists = FALSE; + UINT32 uiCnt; + + for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ ) + { + // go through nodes and save them + if ( gpLeaveListHead[ iCounter ] != NULL ) + { + fNodeExists = TRUE; + + // Save the to specify that a node DOES exist + FileWrite( hFile, &fNodeExists, sizeof(BOOLEAN), &uiNumBytesWritten ); + if( uiNumBytesWritten != sizeof(BOOLEAN) ) + { + return(FALSE); + } + + uiCount = 1; + pCurrentItem = gpLeaveListHead[ iCounter ]; + + //loop through all the nodes to see how many there are + while( pCurrentItem->pNext ) + { + pCurrentItem = pCurrentItem->pNext; + uiCount++; + } + + // Save the number specifing how many items there are in the list + FileWrite( hFile, &uiCount, sizeof(UINT32), &uiNumBytesWritten ); + if( uiNumBytesWritten != sizeof(UINT32) ) + { + return(FALSE); + } + + pCurrentItem = gpLeaveListHead[ iCounter ]; + + //loop through all the nodes to see how many there are + for( uiCnt=0; uiCntpNext; + } + } + else + { + fNodeExists = FALSE; + // Save the to specify that a node DOENST exist + FileWrite( hFile, &fNodeExists, sizeof(BOOLEAN), &uiNumBytesWritten ); + if( uiNumBytesWritten != sizeof(BOOLEAN) ) + { + return(FALSE); + } + } + } + + //Save the leave list profile id's + for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ ) + { + FileWrite( hFile, &guiLeaveListOwnerProfileId[ iCounter ], sizeof(UINT32), &uiNumBytesWritten ); + if( uiNumBytesWritten != sizeof(UINT32) ) + { + return(FALSE); + } + } + + return( TRUE ); +} + + + +BOOLEAN LoadLeaveItemList( HWFILE hFile ) +{ + INT32 iCounter = 0; + MERC_LEAVE_ITEM *pCurrentItem; + MERC_LEAVE_ITEM *pItem; + UINT32 uiCount=0; + UINT32 uiNumBytesRead = 0; + BOOLEAN fNodeExists = FALSE; + UINT32 uiSubItem; + + //Shutdown the list + ShutDownLeaveList( ); + + //init the list + InitLeaveList( ); + + //loop through all the lists + for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ ) + { + // load the flag that specifis that a node DOES exist + FileRead( hFile, &fNodeExists, sizeof(BOOLEAN), &uiNumBytesRead ); + if( uiNumBytesRead != sizeof(BOOLEAN) ) + { + return(FALSE); + } + + // if a root node is supposed to exist + if( fNodeExists ) + { + // load the number specifing how many items there are in the list + FileRead( hFile, &uiCount, sizeof(UINT32), &uiNumBytesRead ); + if( uiNumBytesRead != sizeof(UINT32) ) + { + return(FALSE); + } + + // allocate space + gpLeaveListHead[ iCounter ] = (MERC_LEAVE_ITEM *) MemAlloc( sizeof( MERC_LEAVE_ITEM ) ); + if( gpLeaveListHead[ iCounter ] == NULL ) + { + return( FALSE ); + } + memset( gpLeaveListHead[ iCounter ], 0, sizeof( MERC_LEAVE_ITEM ) ); + + pCurrentItem = gpLeaveListHead[ iCounter ]; + + for( uiSubItem=0; uiSubItem< uiCount; uiSubItem++ ) + { + // allocate space + pItem = (MERC_LEAVE_ITEM *) MemAlloc( sizeof( MERC_LEAVE_ITEM ) ); + if( pItem == NULL ) + { + return( FALSE ); + } + memset( pItem, 0, sizeof( MERC_LEAVE_ITEM ) ); + + // Load the items + FileRead( hFile, pItem, sizeof( MERC_LEAVE_ITEM ), &uiNumBytesRead ); + if( uiNumBytesRead != sizeof( MERC_LEAVE_ITEM ) ) + { + return(FALSE); + } + + + pItem->pNext = NULL; + + //add the node to the list + if( uiSubItem == 0 ) + { + gpLeaveListHead[ iCounter ] = pItem; + pCurrentItem = gpLeaveListHead[ iCounter ]; + } + else + { + pCurrentItem->pNext = pItem; + pCurrentItem = pCurrentItem->pNext; + } + } + } + } + + //Load the leave list profile id's + for( iCounter = 0; iCounter < NUM_LEAVE_LIST_SLOTS; iCounter++ ) + { + FileRead( hFile, &guiLeaveListOwnerProfileId[ iCounter ], sizeof(UINT32), &uiNumBytesRead ); + if( uiNumBytesRead != sizeof(UINT32) ) + { + return(FALSE); + } + } + + return( TRUE ); +} + + + +void TurnOnSectorLocator( UINT8 ubProfileID ) +{ + SOLDIERTYPE *pSoldier; + + Assert( ubProfileID != NO_PROFILE ); + + pSoldier = FindSoldierByProfileID( ubProfileID, FALSE ); + if( pSoldier ) + { + gsSectorLocatorX = pSoldier->sSectorX; + gsSectorLocatorY = pSoldier->sSectorY; + } + else + { + // if it's Skyrider (when he's not on our team), and his chopper has been setup + if ( ( ubProfileID == SKYRIDER ) && fSkyRiderSetUp ) + { + // if helicopter position is being shown, don't do this, too, cause the helicopter icon is on top and it looks + // like crap. I tried moving the heli icon blit to before, but that screws up it's blitting. + if ( !fShowAircraftFlag ) + { + // can't use his profile, he's where his chopper is + Assert( iHelicopterVehicleId != -1 ); + gsSectorLocatorX = pVehicleList[ iHelicopterVehicleId ].sSectorX; + gsSectorLocatorY = pVehicleList[ iHelicopterVehicleId ].sSectorY; + } + else + { + return; + } + } + else + { + gsSectorLocatorX = gMercProfiles[ ubProfileID ].sSectorX; + gsSectorLocatorY = gMercProfiles[ ubProfileID ].sSectorY; + } + } + gubBlitSectorLocatorCode = LOCATOR_COLOR_YELLOW; +} + + +void TurnOffSectorLocator() +{ + gubBlitSectorLocatorCode = LOCATOR_COLOR_NONE; + fMapPanelDirty = TRUE; +} + + + +void HandleBlitOfSectorLocatorIcon( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ, UINT8 ubLocatorID ) +{ + static UINT8 ubFrame = 0; + UINT8 ubBaseFrame = 0; + UINT32 uiTimer = 0; + HVOBJECT hHandle; + INT16 sScreenX, sScreenY; + + + // blits at 0,0 had been observerd... + Assert( ( sSectorX >= 1 ) && ( sSectorX <= 16 ) ); + Assert( ( sSectorY >= 1 ) && ( sSectorY <= 16 ) ); + Assert( ( sSectorZ >= 0 ) && ( sSectorZ <= 3 ) ); + + if( sSectorZ != iCurrentMapSectorZ ) + { //if the z level of the map screen renderer is different than the + //sector z that we wish to locate, then don't render it + return; + } + + // if showing sector inventory, don't do this + if( fShowMapInventoryPool ) + { + return; + } + + + GetVideoObject( &hHandle, guiSectorLocatorGraphicID ); + + switch( ubLocatorID ) + { + // grab zoomed out icon + case LOCATOR_COLOR_RED: + ubBaseFrame = 0; + ubFrame = (UINT8)(ubFrame % 13); + break; + case LOCATOR_COLOR_YELLOW: + ubBaseFrame = 13; + ubFrame = (UINT8)(13 + (ubFrame % 13) ); + break; + default: + //not supported + return; + } + + //Convert the sector value into screen values. + GetScreenXYFromMapXY( sSectorX, sSectorY, &sScreenX, &sScreenY ); + // make sure we are on the border + if( sScreenX < MAP_GRID_X ) + { + sScreenX = MAP_GRID_X; + } + sScreenY--; //Carterism ritual + if( sScreenY < MAP_GRID_Y ) + { + sScreenY = MAP_GRID_Y; + } + + uiTimer = GetJA2Clock(); + + // if first time in, reset value + if( guiSectorLocatorBaseTime == 0 ) + { + guiSectorLocatorBaseTime = GetJA2Clock( ); + } + + // check if enough time has passed to update the frame counter + if( ANIMATED_BATTLEICON_FRAME_TIME < ( uiTimer - guiSectorLocatorBaseTime ) ) + { + guiSectorLocatorBaseTime = uiTimer; + ubFrame++; + + if( ubFrame > ubBaseFrame + MAX_FRAME_COUNT_FOR_ANIMATED_BATTLE_ICON ) + { + ubFrame = ubBaseFrame; + } + } + + RestoreExternBackgroundRect( (INT16)(sScreenX + 1), (INT16)(sScreenY - 1), MAP_GRID_X , MAP_GRID_Y ); + + // blit object to frame buffer + BltVideoObject( FRAME_BUFFER, hHandle, ubFrame, sScreenX, sScreenY, VO_BLT_SRCTRANSPARENCY, NULL ); + + // invalidate region on frame buffer + InvalidateRegion( sScreenX, sScreenY - 1, sScreenX + MAP_GRID_X , sScreenY + MAP_GRID_Y ); + +} + + + +BOOLEAN CheckIfSalaryIncreasedAndSayQuote( SOLDIERTYPE *pSoldier, BOOLEAN fTriggerContractMenu ) +{ + Assert( pSoldier ); + + // OK, check if their price has gone up + if( pSoldier->fContractPriceHasIncreased ) + { + if ( fTriggerContractMenu ) + { + // have him say so first - post the dialogue event with the contract menu event + SpecialCharacterDialogueEvent( DIALOGUE_SPECIAL_EVENT_ENTER_MAPSCREEN,0,0,0,0,0 ); + HandleImportantMercQuote( pSoldier, QUOTE_MERC_GONE_UP_IN_PRICE ); + TacticalCharacterDialogueWithSpecialEvent( pSoldier, 0, DIALOGUE_SPECIAL_EVENT_SHOW_CONTRACT_MENU, 0,0 ); + } + else + { + // now post the dialogue event and the contratc menu event + HandleImportantMercQuote( pSoldier, QUOTE_MERC_GONE_UP_IN_PRICE ); + } + + pSoldier->fContractPriceHasIncreased = FALSE; + + // said quote / triggered contract menu + return( TRUE ); + } + else + { + // nope, nothing to do + return( FALSE ); + } +} diff --git a/Strategic/Map Screen Interface_NEW.h b/Strategic/Map Screen Interface_NEW.h new file mode 100644 index 00000000..dff205d9 --- /dev/null +++ b/Strategic/Map Screen Interface_NEW.h @@ -0,0 +1,606 @@ +#ifndef MAP_SCREEN_INTERFACE_H +#define MAP_SCREEN_INTERFACE_H + + +#include "Types.h" +#include "Soldier Control.h" +#include "MessageBoxScreen.h" + + + +typedef struct FASTHELPREGION { + // the string + CHAR16 FastHelpText[ 256 ]; + + // the x and y position values + INT32 iX; + INT32 iY; + INT32 iW; + +} FASTHELPREGION; + + +// String Lengths Defines +#define MAX_NAME_LENGTH 10 +#define MAX_LOCATION_SIZE 8 +#define MAX_DESTETA_SIZE 8 +#define MAX_ASSIGN_SIZE 10 +#define MAX_TIME_REMAINING_SIZE 8 + + +// char breath and life position +#define BAR_INFO_X 66 +#define BAR_INFO_Y 61 + +// merc icon position +#define CHAR_ICON_CONTRACT_Y 64 +#define CHAR_ICON_X 187 +#define CHAR_ICON_WIDTH 10 +#define CHAR_ICON_HEIGHT 10 +#define CHAR_ICON_SPACING 13 + +// max number of characters and vehicles +//Character List Length +#define MAX_CHARACTER_COUNT 20 +#define MAX_VEHICLE_COUNT 20 + +// map screen font +#define MAP_SCREEN_FONT BLOCKFONT2 + +// characterlist regions +#define Y_START 135 //146 +#define MAP_START_KEYRING_Y 107 +#define Y_SIZE GetFontHeight(MAP_SCREEN_FONT) + + +// attribute menu defines (must match NUM_TRAINABLE_STATS defines, and pAttributeMenuStrings ) +enum { + ATTRIB_MENU_STR=0, + ATTRIB_MENU_DEX, + ATTRIB_MENU_AGI, + ATTRIB_MENU_HEA, + ATTRIB_MENU_MARK, + ATTRIB_MENU_MED, + ATTRIB_MENU_MECH, + ATTRIB_MENU_LEAD, + ATTRIB_MENU_EXPLOS, + ATTRIB_MENU_CANCEL, + MAX_ATTRIBUTE_STRING_COUNT, +}; + +// the epc assignment menu +enum{ + EPC_MENU_ON_DUTY = 0, + EPC_MENU_PATIENT, + EPC_MENU_VEHICLE, + EPC_MENU_REMOVE, + EPC_MENU_CANCEL, + MAX_EPC_MENU_STRING_COUNT, +}; + +// assignment menu defines +enum { + ASSIGN_MENU_ON_DUTY=0, + ASSIGN_MENU_DOCTOR, + ASSIGN_MENU_PATIENT, + ASSIGN_MENU_VEHICLE, + ASSIGN_MENU_REPAIR, + ASSIGN_MENU_TRAIN, + ASSIGN_MENU_CANCEL, + MAX_ASSIGN_STRING_COUNT, +}; + + +// training assignment menu defines +enum { + TRAIN_MENU_SELF, + TRAIN_MENU_TOWN, + TRAIN_MENU_TEAMMATES, + TRAIN_MENU_TRAIN_BY_OTHER, + TRAIN_MENU_CANCEL, + MAX_TRAIN_STRING_COUNT, +}; + + +// the remove merc from team pop up box strings +enum{ + REMOVE_MERC = 0, + REMOVE_MERC_CANCEL, + MAX_REMOVE_MERC_COUNT, +}; + + +// squad menu defines +enum{ + SQUAD_MENU_1, + SQUAD_MENU_2, + SQUAD_MENU_3, + SQUAD_MENU_4, + SQUAD_MENU_5, + SQUAD_MENU_6, + SQUAD_MENU_7, + SQUAD_MENU_8, + SQUAD_MENU_9, + SQUAD_MENU_10, + SQUAD_MENU_11, + SQUAD_MENU_12, + SQUAD_MENU_13, + SQUAD_MENU_14, + SQUAD_MENU_15, + SQUAD_MENU_16, + SQUAD_MENU_17, + SQUAD_MENU_18, + SQUAD_MENU_19, + SQUAD_MENU_20, + SQUAD_MENU_CANCEL, + MAX_SQUAD_MENU_STRING_COUNT, +}; + + +// contract menu defines +enum{ + CONTRACT_MENU_CURRENT_FUNDS = 0, + CONTRACT_MENU_SPACE, + CONTRACT_MENU_DAY, + CONTRACT_MENU_WEEK, + CONTRACT_MENU_TWO_WEEKS, + CONTRACT_MENU_TERMINATE, + CONTRACT_MENU_CANCEL, + MAX_CONTRACT_MENU_STRING_COUNT, +}; + +// enums for pre battle interface pop ups +enum +{ + ASSIGNMENT_POPUP, + DESTINATION_POPUP, + CONTRACT_POPUP +}; + + +enum{ + NO_REASON_FOR_UPDATE = 0, + CONTRACT_FINISHED_FOR_UPDATE, + ASSIGNMENT_FINISHED_FOR_UPDATE, + ASSIGNMENT_RETURNING_FOR_UPDATE, + ASLEEP_GOING_AUTO_FOR_UPDATE, + CONTRACT_EXPIRE_WARNING_REASON, +}; + + +enum{ + START_RED_SECTOR_LOCATOR = 0, + STOP_RED_SECTOR_LOCATOR, + START_YELLOW_SECTOR_LOCATOR, + STOP_YELLOW_SECTOR_LOCATOR, +}; + + +// dimensions and offset for merc update box +#define UPDATE_MERC_FACE_X_WIDTH 50 +#define UPDATE_MERC_FACE_X_HEIGHT 50 +#define UPDATE_MERC_FACE_X_OFFSET 2 +#define UPDATE_MERC_FACE_Y_OFFSET 2 +#define WIDTH_OF_UPDATE_PANEL_BLOCKS 50 +#define HEIGHT_OF_UPDATE_PANEL_BLOCKS 50 +#define UPDATE_MERC_Y_OFFSET 4 +#define UPDATE_MERC_X_OFFSET 4 + + +// dimensions and offset for merc update box +#define TACT_UPDATE_MERC_FACE_X_WIDTH 70 +#define TACT_UPDATE_MERC_FACE_X_HEIGHT 49 +#define TACT_UPDATE_MERC_FACE_X_OFFSET 8 +#define TACT_UPDATE_MERC_FACE_Y_OFFSET 6 +#define TACT_WIDTH_OF_UPDATE_PANEL_BLOCKS 70 +#define TACT_HEIGHT_OF_UPDATE_PANEL_BLOCKS 49 +#define TACT_UPDATE_MERC_Y_OFFSET 4 +#define TACT_UPDATE_MERC_X_OFFSET 4 + + +// the first vehicle slot int he list +#define FIRST_VEHICLE 18 + +typedef struct MERC_LEAVE_ITEM{ + OBJECTTYPE o; + struct MERC_LEAVE_ITEM *pNext; +}MERC_LEAVE_ITEM; + +extern BOOLEAN fShowAssignmentMenu; +extern BOOLEAN fShowTrainingMenu ; +extern BOOLEAN fShowAttributeMenu; +extern BOOLEAN fShowSquadMenu ; +extern BOOLEAN fShowContractMenu ; +extern BOOLEAN fShowRemoveMenu ; + +extern BOOLEAN fFirstTimeInMapScreen; +extern BOOLEAN fLockOutMapScreenInterface; + +// The character data structure +typedef struct { + + UINT16 usSolID;// soldier ID in MenPtrs + BOOLEAN fValid;// is the current soldier a valid soldier + +} MapScreenCharacterSt; + + +// map screen character structure list, contrains soldier ids into menptr +extern MapScreenCharacterSt gCharactersList[ ]; + +extern BOOLEAN fShowMapScreenHelpText; + + +// map inventory pool inited +extern BOOLEAN fMapInventoryPoolInited; + +// highlighted lines +extern INT32 giHighLine; +extern INT32 giAssignHighLine; +extern INT32 giDestHighLine; +extern INT32 giContractHighLine; +extern INT32 giSleepHighLine; + +extern UINT32 guiUpdatePanel; +extern UINT32 guiUpdatePanelTactical; +extern BOOLEAN fShowUpdateBox; + +extern SGPRect ContractDimensions; +extern SGPPoint ContractPosition; +extern SGPRect AttributeDimensions; +extern SGPPoint AttributePosition; +extern SGPRect TrainDimensions; +extern SGPPoint TrainPosition; +extern SGPRect VehicleDimensions; +extern SGPPoint VehiclePosition; +extern SGPRect AssignmentDimensions ; +extern SGPPoint AssignmentPosition ; +extern SGPPoint SquadPosition ; +extern SGPRect SquadDimensions ; + +extern SGPPoint RepairPosition; +extern SGPRect RepairDimensions; + +extern SGPPoint OrigContractPosition; +extern SGPPoint OrigAttributePosition; +extern SGPPoint OrigSquadPosition ; +extern SGPPoint OrigAssignmentPosition ; +extern SGPPoint OrigTrainPosition; +extern SGPPoint OrigVehiclePosition; + +// disble team info panel due to showing of battle roster +extern BOOLEAN fDisableDueToBattleRoster; + +extern BOOLEAN gfAtLeastOneMercWasHired; + +// curtrent map sector z that is being displayed in the mapscreen +extern INT32 iCurrentMapSectorZ; + +// y position of the pop up box +extern INT32 giBoxY; + +// pop up box textures +extern UINT32 guiPOPUPTEX; +extern UINT32 guiPOPUPBORDERS; + +// the level-changing markers on the map border +extern UINT32 guiLEVELMARKER; + +// the currently selected character arrow +extern UINT32 guiSelectedCharArrow; + +// sam and mine icons +extern UINT32 guiSAMICON; + +extern BOOLEAN fShowMapScreenMovementList; + +// do we need to rebuild the mapscreen characterlist? +extern BOOLEAN fReBuildCharacterList; + +// restore glow rotation in contract region glow boxes +extern BOOLEAN fResetContractGlow; + +// init vehicle and characters list +void InitalizeVehicleAndCharacterList( void ); + +// set this entry to as selected +void SetEntryInSelectedCharacterList( INT8 bEntry ); +// set this entry to as unselected +void ResetEntryForSelectedList( INT8 bEntry ); + +// reset selected list +void ResetSelectedListForMapScreen( ); + +// build a selected list from a to b, inclusive +void BuildSelectedListFromAToB( INT8 bA, INT8 bB ); + +// isa this entry int he selected character list set? +BOOLEAN IsEntryInSelectedListSet( INT8 bEntry ); + +// is there more than one person selected? +BOOLEAN MultipleCharacterListEntriesSelected( void ); + +// toggle this entry on or off +void ToggleEntryInSelectedList( INT8 bEntry ); + +// reset assignments for mercs on selected list who have this assignment +void ResetAssignmentsForMercsTrainingUnpaidSectorsInSelectedList( INT8 bAssignment ); + +/* +// plot path for selected character list +void PlotPathForSelectedCharacterList( INT16 sX, INT16 sY ); +*/ + +void RestoreBackgroundForAssignmentGlowRegionList( void ); +void RestoreBackgroundForDestinationGlowRegionList( void ); +void RestoreBackgroundForContractGlowRegionList( void ); +void RestoreBackgroundForSleepGlowRegionList( void ); + +// play click when we are entering a glow region +void PlayGlowRegionSound( void ); + +// is this character in the action of plotting a path? +INT16 CharacterIsGettingPathPlotted( INT16 sCharNumber ); + +// disable team info panels +void DisableTeamInfoPanels( void ); + +// enable team info panels +void EnableTeamInfoPanels( void ); + +// activate pop up for soldiers in the pre battle interface +void ActivateSoldierPopup( SOLDIERTYPE *pSoldier, UINT8 ubPopupType, INT16 xp, INT16 yp ); + +// do mapscreen message box +INT32 DoMapMessageBox( UINT8 ubStyle, INT16 * zString, UINT32 uiExitScreen, UINT16 usFlags, MSGBOX_CALLBACK ReturnCallback ); + +// hop up one leve,l int he map screen level interface +void GoUpOneLevelInMap( void ); + +// go down one level in the mapscreen map interface +void GoDownOneLevelInMap( void ); + +// jump to this level on the map +void JumpToLevel( INT32 iLevel ); + +// check to see if we need to update the screen +void CheckAndUpdateBasedOnContractTimes( void ); + +// check if are just about to display this pop up or stopping display +void HandleDisplayOfItemPopUpForSector( INT16 sMapX, INT16 sMapY, INT16 sMapZ ); + +// display red arrow by name of selected merc +void HandleDisplayOfSelectedMercArrows( void ); + +// check which guys can move with this guy +void DeselectSelectedListMercsWhoCantMoveWithThisGuy( SOLDIERTYPE *pSoldier ); + +// get morale string for this grunt given this morale level +void GetMoraleString( SOLDIERTYPE *pSoldier, STR16 sString ); + +// handle leaving of equipment in sector +void HandleLeavingOfEquipmentInCurrentSector( UINT32 uiMercId ); + +// set up a linked list of items being dropped and post an event to later drop them +void HandleMercLeavingEquipmentInDrassen( UINT32 uiMercId ); +void HandleMercLeavingEquipmentInOmerta( UINT32 uiMercId ); + +// actually drop the stored list of items +void HandleEquipmentLeftInOmerta( UINT32 uiSlotIndex ); +void HandleEquipmentLeftInDrassen( UINT32 uiSlotIndex ); + +// init/shutdown leave item lists +void InitLeaveList( void ); +void ShutDownLeaveList( void ); + +// add item to leave equip index +BOOLEAN AddItemToLeaveIndex( OBJECTTYPE *o, UINT32 uiIndex ); + +// release memory for all items in this slot's leave item list +void FreeLeaveListSlot( UINT32 uiSlotIndex ); + +// first free slot in equip leave list +INT32 FindFreeSlotInLeaveList( void ); + +// set up drop list +INT32 SetUpDropItemListForMerc( UINT32 uiMercId ); +// store owner's profile id for the items added to this leave slot index +void SetUpMercAboutToLeaveEquipment( UINT32 ubProfileId, UINT32 uiSlotIndex ); + +// remove item from leave index +//BOOLEAN RemoveItemFromLeaveIndex( MERC_LEAVE_ITEM *pItem, UINT32 uiIndex ); + +// handle a group about to arrive in a sector +void HandleGroupAboutToArrive( void ); + +// up arrow +void HandleMapScreenUpArrow( void ); +void HandleMapScreenDownArrow( void ); + + +// create and destroy the status bars mouse region +void CreateMapStatusBarsRegion( void ); +void RemoveMapStatusBarsRegion( void ); +void UpdateCharRegionHelpText( void ); + +// find this soldier in mapscreen character list and set as contract +void FindAndSetThisContractSoldier( SOLDIERTYPE *pSoldier ); + +// lose the cursor, re-render +void HandleMAPUILoseCursorFromOtherScreen( void ); + +void RenderMapRegionBackground( void ); + +// update mapscreen assignment positions +void UpdateMapScreenAssignmentPositions( void ); + +// get the umber of valid mercs in the mapscreen character list +INT32 GetNumberOfPeopleInCharacterList( void ); + +// the next and previous people in the mapscreen +void GoToPrevCharacterInList( void ); +void GoToNextCharacterInList( void ); + +// this does the whole miner giving player info speil +void HandleMinerEvent( UINT8 bMinerNumber, INT16 sSectorX, INT16 sSectorY, INT16 sQuoteNumber, BOOLEAN fForceMapscreen ); + +// set up the event of animating a mine sector +void SetUpAnimationOfMineSectors( INT32 iEvent ); + +// display map screen +void DisplayMapScreenFastHelpList( void ); + +// handle display of fast help +void HandleDisplayOfExitToTacticalMessageForFirstEntryToMapScreen( void ); + +// is the text up? +BOOLEAN IsMapScreenHelpTextUp( void ); + +// stop the help text in mapscreen +void StopMapScreenHelpText( void ); + +// set up the help text +void SetUpMapScreenFastHelpText( void ); + +void TurnOnSectorLocator( UINT8 ubProfileID ); +void TurnOffSectorLocator(); + +extern INT16 gsSectorLocatorX; +extern INT16 gsSectorLocatorY; +extern UINT8 gubBlitSectorLocatorCode; + +enum +{ + LOCATOR_COLOR_NONE, + LOCATOR_COLOR_RED, + LOCATOR_COLOR_YELLOW +}; + +extern UINT32 guiSectorLocatorGraphicID; +void HandleBlitOfSectorLocatorIcon( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ, UINT8 ubLocatorID ); + + +// the tactical version + +// handle the actual showingof the list +void HandleShowingOfTacticalInterfaceFastHelpText( void ); + +// start showing the list +void StartShowingInterfaceFastHelpText( void ); + +// stop showing the list +void StopShowingInterfaceFastHelpText( void ); + +// is the list active? +BOOLEAN IsTheInterfaceFastHelpTextActive( void ); + +//set up the tactical lists +BOOLEAN SetUpFastHelpListRegions( INT32 iXPosition[], INT32 iYPosition[], INT32 iWidth[], STR16 sString[], INT32 iSize ); + + +// the alternate mapscreen movement system +void InitializeMovingLists( void ); + +// reset assignment for mercs trainign militia in this sector +void ResetAssignmentOfMercsThatWereTrainingMilitiaInThisSector( INT16 sSectorX, INT16 sSectorY ); + + +// the sector move box +void DeselectSquadForMovement( INT32 iSquadNumber ); +void SelectedSquadForMovement( INT32 iSquadNumber ); +void DeselectSoldierForMovement( SOLDIERTYPE *pSoldier ); +void SelectSoldierForMovement( SOLDIERTYPE *pSoldier ); +void SelectVehicleForMovement( INT32 iVehicleId, BOOLEAN fAndAllOnBoard ); +void DeselectVehicleForMovement( INT32 iVehicleId ); +void AddVehicleToMovingLists( INT32 iVehicleId ); +void AddSquadToMovingLists( INT32 iSquadNumber ); +void AddSoldierToMovingLists( SOLDIERTYPE *pSoldier ); +void CreateDestroyMovementBox( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ ); +void SetUpMovingListsForSector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ ); +void ReBuildMoveBox( void ); +BOOLEAN IsCharacterSelectedForAssignment( INT16 sCharNumber ); +BOOLEAN IsCharacterSelectedForSleep( INT16 sCharNumber ); + +// the update box +void CreateDestroyTheUpdateBox( void ); +void SetSoldierUpdateBoxReason( INT32 iReason ); +void AddSoldierToUpdateBox( SOLDIERTYPE *pSoldier ); +void ResetSoldierUpdateBox( void ); +void DisplaySoldierUpdateBox( ); +BOOLEAN IsThePopUpBoxEmpty( void ); + + +// unmarking buttons dirty for dialogue +void UpdateButtonsDuringCharacterDialogue( void ); +void UpdateButtonsDuringCharacterDialogueSubTitles( void ); +void SetUpdateBoxFlag( BOOLEAN fFlag ); + + + +/// set the town of Tixa as found by the player +void SetTixaAsFound( void ); + +// set the town of Orta as found by the player +void SetOrtaAsFound( void ); + +// set this SAM site as being found by the player +void SetSAMSiteAsFound( UINT8 uiSamIndex ); + +// init time menus +void InitTimersForMoveMenuMouseRegions( void ); + +// the screen mask +void CreateScreenMaskForMoveBox( void ); +void RemoveScreenMaskForMoveBox( void ); + + +// help text to show user merc has insurance +void UpdateHelpTextForMapScreenMercIcons( void ); +void CreateDestroyInsuranceMouseRegionForMercs( BOOLEAN fCreate ); + + +// stuff to deal with player just starting the game +BOOLEAN HandleTimeCompressWithTeamJackedInAndGearedToGo( void ); +//void HandlePlayerEnteringMapScreenBeforeGoingToTactical( void ); + +// handle sector being taken over uncontested +BOOLEAN NotifyPlayerWhenEnemyTakesControlOfImportantSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, BOOLEAN fContested ); + +// handle notifying player of invasion by enemy +void NotifyPlayerOfInvasionByEnemyForces( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, MSGBOX_CALLBACK ReturnCallback ); + +void ShutDownUserDefineHelpTextRegions( void ); + +// shwo the update box +void ShowUpdateBox( void ); + +// add special events +void AddSoldierToWaitingListQueue( SOLDIERTYPE *pSoldier ); +void AddReasonToWaitingListQueue( INT32 iReason ); +void AddDisplayBoxToWaitingQueue( void ); + +// can this group move it out +BOOLEAN CanEntireMovementGroupMercIsInMove( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber ); +void ReportMapScreenMovementError( INT8 bErrorNumber ); + +void HandleRebuildingOfMapScreenCharacterList( void ); + +void RequestToggleTimeCompression( void ); +void RequestIncreaseInTimeCompression( void ); +void RequestDecreaseInTimeCompression( void ); + +void SelectUnselectedMercsWhoMustMoveWithThisGuy( void ); +BOOLEAN AnyMercInSameSquadOrVehicleIsSelected( SOLDIERTYPE *pSoldier ); + +BOOLEAN LoadLeaveItemList( HWFILE hFile ); +BOOLEAN SaveLeaveItemList( HWFILE hFile ); + +BOOLEAN CheckIfSalaryIncreasedAndSayQuote( SOLDIERTYPE *pSoldier, BOOLEAN fTriggerContractMenu ); + +void EndUpdateBox( BOOLEAN fContinueTimeCompression ); + +extern BOOLEAN CanCharacterMoveInStrategic( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber ); +extern BOOLEAN MapscreenCanPassItemToCharNum( INT32 iNewCharSlot ); + + +#endif \ No newline at end of file diff --git a/Strategic/Quest Debug System.cpp b/Strategic/Quest Debug System.cpp index 1e4acbec..a0ce0ae3 100644 --- a/Strategic/Quest Debug System.cpp +++ b/Strategic/Quest Debug System.cpp @@ -196,8 +196,8 @@ typedef void ( *DROP_DOWN_SELECT_CALLBACK ) (STR16); -#define CLOCK_X 554 -#define CLOCK_Y 459 +//#define CLOCK_X 554 +//#define CLOCK_Y 459 #define QDS_BUTTON_HEIGHT 21 diff --git a/Strategic/Strategic AI.cpp b/Strategic/Strategic AI.cpp index bf94b922..71c37c33 100644 --- a/Strategic/Strategic AI.cpp +++ b/Strategic/Strategic AI.cpp @@ -1,4 +1,4 @@ - +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #include "GameSettings.h" @@ -693,6 +693,12 @@ void ValidateGroup( GROUP *pGroup ) INT32 iMaxEnemyGroupSize = gGameExternalOptions.iMaxEnemyGroupSize; DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic2"); + // WANNE 2 + if (pGroup == NULL) + { + return; + } + if( !pGroup->ubSectorX || !pGroup->ubSectorY || pGroup->ubSectorX > 16 || pGroup->ubSectorY > 16 ) { if( gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) diff --git a/Strategic/mapscreen.cpp b/Strategic/mapscreen.cpp index 03ebff9f..16f9bb29 100644 --- a/Strategic/mapscreen.cpp +++ b/Strategic/mapscreen.cpp @@ -1,3 +1,4 @@ +// WANNE 2 SCROLL BUTTONS CODE IS OUTCOMMENTED (search for // WANNE 2 ) #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #include "HelpScreen.h" @@ -166,54 +167,56 @@ #define MAP_WEIGHT_PERCENT_X 196 #define MAP_WEIGHT_PERCENT_Y 266 -#define MAP_CAMMO_LABEL_X 178 -#define MAP_CAMMO_LABEL_Y 283 -#define MAP_CAMMO_X 176 -#define MAP_CAMMO_Y 292 +#define MAP_CAMMO_LABEL_X 178 +#define MAP_CAMMO_LABEL_Y 283 +#define MAP_CAMMO_X 176 +#define MAP_CAMMO_Y 292 #define MAP_CAMMO_PERCENT_X 196 #define MAP_CAMMO_PERCENT_Y 293 -#define MAP_PERCENT_WIDTH 20 +#define MAP_PERCENT_WIDTH 20 #define MAP_PERCENT_HEIGHT 10 -#define MAP_INV_STATS_TITLE_FONT_COLOR 6 -#define MAP_INV_STATS_TEXT_FONT_COLOR 5 +#define MAP_INV_STATS_TITLE_FONT_COLOR 6 +#define MAP_INV_STATS_TEXT_FONT_COLOR 5 #define PLAYER_INFO_FACE_START_X 9 #define PLAYER_INFO_FACE_START_Y 17 -#define PLAYER_INFO_FACE_END_X 60 -#define PLAYER_INFO_FACE_END_Y 76 +#define PLAYER_INFO_FACE_END_X 60 +#define PLAYER_INFO_FACE_END_Y 76 #define INV_BODY_X 71 #define INV_BODY_Y 116 +// WANNE 2 +#define NAME_X 4 +#define NAME_WIDTH 55 - NAME_X -#define NAME_X 11 -#define NAME_WIDTH 62 - NAME_X -#define ASSIGN_X 67 -#define ASSIGN_WIDTH 118 - ASSIGN_X -#define SLEEP_X 123 -#define SLEEP_WIDTH 142 - SLEEP_X -#define LOC_X 147 -#define LOC_WIDTH 179 - LOC_X -#define DEST_ETA_X 184 -#define DEST_ETA_WIDTH 217 - DEST_ETA_X -#define TIME_REMAINING_X 222 -#define TIME_REMAINING_WIDTH 250 - TIME_REMAINING_X -#define CLOCK_X_START 463 - 18 -#define CLOCK_Y_START 298 -#define DEST_PLOT_X 463 -#define DEST_PLOT_Y 345 -#define CLOCK_ETA_X 463 - 15 + 6 + 30 -#define CLOCK_HOUR_X_START 463 + 25 + 30 -#define CLOCK_MIN_X_START 463 + 45 + 30 +#define ASSIGN_X 60 +#define ASSIGN_WIDTH 111 - ASSIGN_X +#define SLEEP_X 116 +#define SLEEP_WIDTH 135 - SLEEP_X +#define LOC_X 140 +#define LOC_WIDTH 172 - LOC_X +#define DEST_ETA_X 177 +#define DEST_ETA_WIDTH 210 - DEST_ETA_X +#define TIME_REMAINING_X 215 +#define TIME_REMAINING_WIDTH 243 - TIME_REMAINING_X +// WANNE 2 +#define CLOCK_Y_START (MAP_BORDER_Y_OFFSET + 298) // 298 + +#define DEST_PLOT_X (MAP_BORDER_X_OFFSET + 463) //463 +#define DEST_PLOT_Y (MAP_BORDER_Y_OFFSET + 345) //345 + +// WANNE 2 +#define CLOCK_ETA_X (MAP_BORDER_X_OFFSET + 484) //463 - 15 + 6 + 30 +#define CLOCK_HOUR_X_START (MAP_BORDER_X_OFFSET + 518) //463 + 25 + 30 +#define CLOCK_MIN_X_START (MAP_BORDER_X_OFFSET + 538) //463 + 45 + 30 // contract #define CONTRACT_X 185 #define CONTRACT_Y 50 -//#define CONTRACT_WIDTH 63 -//#define CONTRACT_HEIGHT 10 // trash can #define TRASH_CAN_X 176 @@ -318,8 +321,9 @@ //#define TM_INV_WIDTH 58 //#define TM_INV_HEIGHT 23 -#define CLOCK_X 554 -#define CLOCK_Y 459 +// WANNE 2 (the position of the clock in the strategy screen) +//#define CLOCK_X (SCREEN_WIDTH - 86) //554 +//#define CLOCK_Y (SCREEN_HEIGHT - 21) //459 #define RGB_WHITE ( FROMRGB( 255, 255, 255 ) ) @@ -430,13 +434,23 @@ RGBCOLOR GlowColorsC[]={ */ +//SGPPoint gMapSortButtons[ MAX_SORT_METHODS ]={ +// {12,125}, +// {68,125}, +// {124,125}, +// {148,125}, +// {185,125}, +// {223,125}, +//}; + +// WANNE 2 SGPPoint gMapSortButtons[ MAX_SORT_METHODS ]={ - {12,125}, - {68,125}, - {124,125}, - {148,125}, - {185,125}, - {223,125}, + {5,113}, + {61,113}, + {117,113}, + {141,113}, + {178,113}, + {216,113}, }; @@ -470,8 +484,39 @@ INV_REGION_DESC gSCamoXY = }; +// WANNE 2 +// buttons images +//UINT32 guiMapMercsScrollButtonsImage[ 2 ]; +//UINT32 guiMapMercsScrollButtons[ 2 ]; +// +//UINT32 guiMapVehicleScrollButtonsImage[ 2 ]; +//UINT32 guiMapVehicleScrollButtons [ 2 ]; + + + +extern UINT16 usVehicleY; + +// WANNE 2 +// button enums +//enum{ +// MAP_SCROLL_MERCS_UP =0, +// MAP_SCROLL_MERCS_DOWN, +//}; +// +//enum{ +// MAP_SCROLL_VEHICLE_UP =0, +// MAP_SCROLL_VEHICLE_DOWN, +//}; + + // GLOBAL VARIABLES (OURS) +// WANNE 2 +//void CreateButtonsForScrolling(void); +//void DeleteButtonsForScrolling(void); + +void BtnMessageUpMapScreenCallback( GUI_BUTTON *btn,INT32 reason ); +BOOLEAN fScrollButtonsInitialized = FALSE; BOOLEAN fFlashAssignDone = FALSE; BOOLEAN fInMapMode = FALSE; @@ -1129,7 +1174,6 @@ void ContractBoxGlow( void ) } - void ContractListRegionBoxGlow( UINT16 usCount ) { static INT32 iColorNum =10; @@ -1139,6 +1183,8 @@ void ContractListRegionBoxGlow( UINT16 usCount ) UINT8 *pDestBuf; INT16 usY = 0; INT16 sYAdd = 0; + INT16 sYStart = 0; + INT16 usVehicleCount = 0; // if not glowing right now, leave @@ -1167,17 +1213,24 @@ void ContractListRegionBoxGlow( UINT16 usCount ) iColorNum--; + // WANNE 2 if( usCount >= FIRST_VEHICLE ) { - sYAdd = 6; + usVehicleCount = usCount - FIRST_VEHICLE; + sYStart = usVehicleY; + usY=(Y_OFFSET*usVehicleCount-1)+(sYStart+(usVehicleCount*Y_SIZE)); } else { - sYAdd = 0; + sYStart = Y_START; + usY=(Y_OFFSET*usCount-1)+(sYStart+(usCount*Y_SIZE)); } // y start position of box - usY=(Y_OFFSET*usCount-1)+(Y_START+(usCount*Y_SIZE) + sYAdd ); + //usY=(Y_OFFSET*usCount-1)+(Y_START+(usCount*Y_SIZE) + sYAdd ); + + // WANNE 2 + //usY=(Y_OFFSET*usCount-1)+(sYStart+(usCount*Y_SIZE)); // glow contract box usColor=Get16BPPColor( FROMRGB( GlowColorsA[iColorNum].ubRed, GlowColorsA[iColorNum].ubGreen, GlowColorsA[iColorNum].ubBlue ) ); @@ -2457,6 +2510,8 @@ void DisplayGroundEta( void ) SetFont( ETA_FONT ); SetFontForeground( FONT_LTGREEN ); SetFontBackground( FONT_BLACK ); + + // WANNE 2 mprintf( CLOCK_ETA_X, CLOCK_Y_START, pEtaString[ 0 ] ); // if less than one day @@ -2487,6 +2542,7 @@ void HighLightAssignLine() INT16 usCount = 0; UINT16 usX; UINT16 usY; + INT16 usVehicleCount = 0; // is this a valid line? @@ -2520,16 +2576,6 @@ void HighLightAssignLine() else iColorNum--; - - //usY=Y_START+(giHighLine*GetFontHeight((MAP_SCREEN_FONT))); - usY = ( Y_OFFSET * giAssignHighLine - 1 ) + ( Y_START + ( giAssignHighLine * Y_SIZE ) ); - - if( giAssignHighLine >= FIRST_VEHICLE ) - { - usY += 6; - } - - pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); @@ -2540,9 +2586,12 @@ void HighLightAssignLine() usX=ASSIGN_X; //usY=Y_START+(giHighLine*GetFontHeight((MAP_SCREEN_FONT))); usY=(Y_OFFSET*usCount-1)+(Y_START+(usCount*Y_SIZE)); + + // WANNE 2 if( usCount >= FIRST_VEHICLE ) { - usY += 6; + usVehicleCount = usCount - FIRST_VEHICLE; + usY = (Y_OFFSET*usVehicleCount-1)+(usVehicleY+(usVehicleCount*Y_SIZE)); } usColor=Get16BPPColor( FROMRGB( GlowColorsA[iColorNum].ubRed, GlowColorsA[iColorNum].ubGreen, GlowColorsA[iColorNum].ubBlue ) ); @@ -2578,6 +2627,7 @@ void HighLightDestLine() UINT16 usCount = 0; UINT16 usX; UINT16 usY; + UINT16 usVehicleCont = 0; if( ( giDestHighLine == -1 ) || fShowInventoryFlag ) @@ -2619,11 +2669,13 @@ void HighLightDestLine() if( CharacterIsGettingPathPlotted( usCount ) == TRUE ) { usX=DEST_ETA_X-4; - //usY=Y_START+(giHighLine*GetFontHeight((MAP_SCREEN_FONT))); usY=(Y_OFFSET*usCount-1)+(Y_START+(usCount*Y_SIZE)); + + // WANNE 2 if( usCount >= FIRST_VEHICLE ) { - usY += 6; + usVehicleCont = usCount - FIRST_VEHICLE; + usY=(Y_OFFSET*usVehicleCont-1)+(usVehicleY+(usVehicleCont*Y_SIZE)); } usColor=Get16BPPColor( FROMRGB( GlowColorsA[iColorNum].ubRed, GlowColorsA[iColorNum].ubGreen, GlowColorsA[iColorNum].ubBlue ) ); @@ -2662,6 +2714,7 @@ void HighLightSleepLine() UINT16 usCount = 0; UINT16 usX, usX2; UINT16 usY; + UINT16 usVehicleCount = 0; // is this a valid line? @@ -2706,11 +2759,13 @@ void HighLightSleepLine() usX=SLEEP_X-4; usX2 = SLEEP_X + SLEEP_WIDTH; - //usY=Y_START+(giHighLine*GetFontHeight((MAP_SCREEN_FONT))); usY=(Y_OFFSET*usCount-1)+(Y_START+(usCount*Y_SIZE)); + + // WANNE 2 if( usCount >= FIRST_VEHICLE ) { - usY += 6; + usVehicleCount = usCount - FIRST_VEHICLE; + usY=(Y_OFFSET*usVehicleCount-1)+(usVehicleY+(usVehicleCount*Y_SIZE)); } usColor=Get16BPPColor( FROMRGB( GlowColorsA[iColorNum].ubRed, GlowColorsA[iColorNum].ubGreen, GlowColorsA[iColorNum].ubBlue ) ); @@ -2917,7 +2972,7 @@ void DisplayCharacterList() } SetFontForeground( ubForegroundColor ); - + DrawName( Menptr[gCharactersList[sCount].usSolID].name, sCount, MAP_SCREEN_FONT); DrawLocation(sCount, sCount, MAP_SCREEN_FONT); DrawDestination(sCount, sCount, MAP_SCREEN_FONT); @@ -3036,7 +3091,15 @@ UINT32 MapScreenHandle(void) return( MAP_SCREEN ); } - + // WANNE 2 + /*if (fShowInventoryFlag == TRUE) + { + DeleteButtonsForScrolling(); + } + else + { + CreateButtonsForScrolling(); + }*/ // if ( (fInMapMode == FALSE ) && ( fMapExitDueToMessageBox == FALSE ) ) if ( !fInMapMode ) @@ -3073,7 +3136,6 @@ UINT32 MapScreenHandle(void) MoveToEndOfMapScreenMessageList( ); - // if the current time compression mode is something legal in mapscreen, keep it if ( ( giTimeCompressMode >= TIME_COMPRESS_5MINS ) && ( giTimeCompressMode <= TIME_COMPRESS_60MINS ) ) { @@ -3158,8 +3220,20 @@ UINT32 MapScreenHandle(void) /*strcpy(vs_desc.ImageFile, "INTERFACE\\playlist3.pcx"); CHECKF(AddVideoSurface( &vs_desc, &guiCHARLIST ));*/ + // WANNE 2 VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; - FilenameForBPP("INTERFACE\\newgoldpiece3.sti", VObjectDesc.ImageFile ); + if (iResolution == 0) + { + FilenameForBPP("INTERFACE\\newgoldpiece3.sti", VObjectDesc.ImageFile ); + } + else if (iResolution == 1) + { + FilenameForBPP("INTERFACE\\newgoldpiece3_800x600.sti", VObjectDesc.ImageFile ); + } + else if (iResolution == 2) + { + FilenameForBPP("INTERFACE\\newgoldpiece3_1024x768.sti", VObjectDesc.ImageFile ); + } CHECKF(AddVideoObject(&VObjectDesc, &guiCHARLIST)); //VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; @@ -3261,14 +3335,12 @@ UINT32 MapScreenHandle(void) AddVideoObject( &VObjectDesc, &guiNewMailIcons ); } - // create buttons CreateButtonsForMapBorder( ); // create mouse regions for level markers CreateMouseRegionsForLevelMarkers( ); - // change selected sector/level if necessary // NOTE: Must come after border buttons are created, since it may toggle them! if( AnyMercsHired( ) == FALSE ) @@ -3378,6 +3450,21 @@ UINT32 MapScreenHandle(void) // create mouse region for pause clock CreateMouseRegionForPauseOfClock( CLOCK_REGION_START_X, CLOCK_REGION_START_Y ); + // WANNE 2 + + if (iResolution == 0) + { + usVehicleY = 319; + } + else if (iResolution == 1) + { + usVehicleY = 414; + } + else if (iResolution == 2) + { + usVehicleY = 549; + } + // create mouse regions CreateMouseRegionsForTeamList( ); @@ -3806,7 +3893,8 @@ UINT32 MapScreenHandle(void) RenderItemDescriptionBox( ); // render clock - RenderClock(CLOCK_X, CLOCK_Y + 1 ); + // WANNE 2 + RenderClock(CLOCK_X, CLOCK_Y); #ifdef JA2TESTVERSION if( !gfWorldLoaded ) @@ -3816,13 +3904,13 @@ UINT32 MapScreenHandle(void) SetFontForeground( FONT_DKRED ); else SetFontForeground( FONT_RED ); - mprintf( 530, 2, L"TESTVERSION MSG" ); + mprintf( SCREEN_WIDTH - 110, 2, L"TESTVERSION MSG" ); if( GetJA2Clock() % 1000 < 500 ) SetFontForeground( FONT_DKYELLOW ); else SetFontForeground( FONT_YELLOW ); - mprintf( 530, 12, L"NO WORLD LOADED" ); - InvalidateRegion( 530, 2, 640, 23 ); + mprintf( SCREEN_WIDTH - 110, 12, L"NO WORLD LOADED" ); + InvalidateRegion( SCREEN_WIDTH - 110, 2, SCREEN_WIDTH, 23 ); } #endif @@ -4190,18 +4278,23 @@ void SetClockMin(STR16 pStringA, ...) } +// WANNE 2 void DrawName(STR16 pName, INT16 sRowIndex, INT32 iFont) { UINT16 usX=0; UINT16 usY=0; - + + // mercs if( sRowIndex < FIRST_VEHICLE ) { FindFontCenterCoordinates((short)NAME_X + 1, (short)(Y_START+(sRowIndex*Y_SIZE)), (short)NAME_WIDTH, (short)Y_SIZE, pName, (long)iFont, &usX, &usY); } + // vehicles else { - FindFontCenterCoordinates((short)NAME_X + 1, (short)(Y_START+(sRowIndex*Y_SIZE) + 6), (short)NAME_WIDTH, (short)Y_SIZE, pName, (long)iFont, &usX, &usY); + sRowIndex = sRowIndex - FIRST_VEHICLE; + //FindFontCenterCoordinates((short)NAME_X + 1, (short)(Y_START+(sRowIndex*Y_SIZE) + 6), (short)NAME_WIDTH, (short)Y_SIZE, pName, (long)iFont, &usX, &usY); + FindFontCenterCoordinates((short)NAME_X + 1, (short)(usVehicleY+(sRowIndex*Y_SIZE)), (short)NAME_WIDTH, (short)Y_SIZE, pName, (long)iFont, &usX, &usY); } //RestoreExternBackgroundRect(NAME_X, ((UINT16)(usY+(Y_OFFSET*sRowIndex+1))), NAME_WIDTH, Y_SIZE); @@ -4224,7 +4317,10 @@ void DrawAssignment(INT16 sCharNumber, INT16 sRowIndex, INT32 iFont) } else { - FindFontCenterCoordinates((short)ASSIGN_X + 1, (short)(Y_START+(sRowIndex*Y_SIZE) + 6), (short)ASSIGN_WIDTH, (short)Y_SIZE, sString, (long)iFont, &usX, &usY); + // WANNE 2 + sRowIndex = sRowIndex - FIRST_VEHICLE; + //FindFontCenterCoordinates((short)ASSIGN_X + 1, (short)(Y_START+(sRowIndex*Y_SIZE) + 6), (short)ASSIGN_WIDTH, (short)Y_SIZE, sString, (long)iFont, &usX, &usY); + FindFontCenterCoordinates((short)ASSIGN_X + 1, (short)(usVehicleY+(sRowIndex*Y_SIZE)), (short)ASSIGN_WIDTH, (short)Y_SIZE, sString, (long)iFont, &usX, &usY); } if( fFlashAssignDone == TRUE ) @@ -4255,7 +4351,10 @@ void DrawLocation(INT16 sCharNumber, INT16 sRowIndex, INT32 iFont) } else { - FindFontCenterCoordinates((short)LOC_X + 1, (short)(Y_START+(sRowIndex*Y_SIZE) + 6), (short)LOC_WIDTH, (short)Y_SIZE, sString, (long)iFont, &usX, &usY); + // WANNE 2 + //FindFontCenterCoordinates((short)LOC_X + 1, (short)(Y_START+(sRowIndex*Y_SIZE) + 6), (short)LOC_WIDTH, (short)Y_SIZE, sString, (long)iFont, &usX, &usY); + sRowIndex = sRowIndex - FIRST_VEHICLE; + FindFontCenterCoordinates((short)LOC_X + 1, (short)(usVehicleY+(sRowIndex*Y_SIZE)), (short)LOC_WIDTH, (short)Y_SIZE, sString, (long)iFont, &usX, &usY); } // restore background //RestoreExternBackgroundRect(LOC_X, ((UINT16)(usY+(Y_OFFSET*sRowIndex+1))), LOC_WIDTH, Y_SIZE); @@ -4284,7 +4383,10 @@ void DrawDestination(INT16 sCharNumber, INT16 sRowIndex, INT32 iFont) } else { - FindFontCenterCoordinates((short)DEST_ETA_X + 1, (short)(Y_START+(sRowIndex*Y_SIZE) + 6 ), (short)DEST_ETA_WIDTH, (short)Y_SIZE, sString, (long)iFont, &usX, &usY); + // WANNE 2 + sRowIndex = sRowIndex - FIRST_VEHICLE; + //FindFontCenterCoordinates((short)DEST_ETA_X + 1, (short)(Y_START+(sRowIndex*Y_SIZE) + 6 ), (short)DEST_ETA_WIDTH, (short)Y_SIZE, sString, (long)iFont, &usX, &usY); + FindFontCenterCoordinates((short)DEST_ETA_X + 1, (short)(usVehicleY+(sRowIndex*Y_SIZE)), (short)DEST_ETA_WIDTH, (short)Y_SIZE, sString, (long)iFont, &usX, &usY); } //RestoreExternBackgroundRect(DEST_ETA_X+1, ((UINT16)(usY+(Y_OFFSET*sRowIndex+1))), DEST_ETA_WIDTH-1, Y_SIZE); @@ -4317,7 +4419,10 @@ void DrawTimeRemaining( INT16 sCharNumber, INT32 iFont, UINT8 ubFontColor ) } else { - FindFontCenterCoordinates((short)TIME_REMAINING_X + 1, (short)(Y_START+(sCharNumber*Y_SIZE) + 6 ), (short)TIME_REMAINING_WIDTH, (short)Y_SIZE, sString, (long)iFont, &usX, &usY); + // WANNE 2 + sCharNumber = sCharNumber - FIRST_VEHICLE; + //FindFontCenterCoordinates((short)TIME_REMAINING_X + 1, (short)(Y_START+(sCharNumber*Y_SIZE) + 6 ), (short)TIME_REMAINING_WIDTH, (short)Y_SIZE, sString, (long)iFont, &usX, &usY); + FindFontCenterCoordinates((short)TIME_REMAINING_X + 1, (short)(usVehicleY+(sCharNumber*Y_SIZE)), (short)TIME_REMAINING_WIDTH, (short)Y_SIZE, sString, (long)iFont, &usX, &usY); } //RestoreExternBackgroundRect(TIME_REMAINING_X, ((UINT16)(usY+(Y_OFFSET*sCharNumber+1))), TIME_REMAINING_WIDTH, Y_SIZE); @@ -5944,9 +6049,11 @@ void EndMapScreen( BOOLEAN fDuringFade ) // build squad list RebuildCurrentSquad( ); - // DeleteMouseRegionsForLevelMarkers( ); + // WANNE 2 + //DeleteButtonsForScrolling(); + if( fShowMapInventoryPool == FALSE ) { // delete buttons @@ -7413,6 +7520,9 @@ void BlitBackgroundToSaveBuffer( void ) } else if( gfPreBattleInterfaceActive ) { + // WANNE 2 + //DeleteButtonsForScrolling(); + ForceButtonUnDirty( giMapContractButton ); ForceButtonUnDirty( giCharInfoButton[ 0 ] ); ForceButtonUnDirty( giCharInfoButton[ 1 ] ); @@ -7423,12 +7533,15 @@ void BlitBackgroundToSaveBuffer( void ) RenderMapScreenInterfaceBottom( ); } - +// WANNE 2 void CreateMouseRegionsForTeamList( void ) { // will create mouse regions for assignments, path plotting, character info selection INT16 sCounter = 0; - INT16 sYAdd = 0; + //INT16 sYAdd = 0; + + INT16 sYStart = 0; + INT16 sOffsetCounter = 0; // the info region...is the background for the list itself @@ -7436,37 +7549,68 @@ void CreateMouseRegionsForTeamList( void ) { if( sCounter >= FIRST_VEHICLE ) { - sYAdd = 6; + //sYAdd = 6; + sOffsetCounter = sCounter - FIRST_VEHICLE; + sYStart = usVehicleY; } else { - sYAdd = 0; + sOffsetCounter = sCounter; + sYStart = Y_START; + //sYAdd = 0; } + // WANNE 2 // name region - MSYS_DefineRegion( &gTeamListNameRegion[ sCounter ] , NAME_X, ( INT16 )( Y_START + ( sCounter ) * ( Y_SIZE + 2 ) + sYAdd ), NAME_X + NAME_WIDTH, ( INT16 )( 145 + ( sCounter + 1 ) * ( Y_SIZE + 2 ) + sYAdd ), MSYS_PRIORITY_NORMAL, + MSYS_DefineRegion( &gTeamListNameRegion[ sCounter ] , NAME_X, ( INT16 )( sYStart + ( sOffsetCounter ) * ( Y_SIZE + 2 )), NAME_X + NAME_WIDTH, ( INT16 )( (sYStart + 10) + ( sOffsetCounter + 1 ) * ( Y_SIZE + 2 )), MSYS_PRIORITY_NORMAL, MSYS_NO_CURSOR, TeamListInfoRegionMvtCallBack, TeamListInfoRegionBtnCallBack ); // assignment region - MSYS_DefineRegion( &gTeamListAssignmentRegion[ sCounter ] ,ASSIGN_X , ( INT16 )( Y_START + ( sCounter ) * ( Y_SIZE + 2 ) + sYAdd), ASSIGN_X + ASSIGN_WIDTH, ( INT16 )( 145 + ( sCounter + 1 ) * ( Y_SIZE + 2 ) + sYAdd ), MSYS_PRIORITY_NORMAL + 1, + MSYS_DefineRegion( &gTeamListAssignmentRegion[ sCounter ] ,ASSIGN_X , ( INT16 )( sYStart + ( sOffsetCounter ) * ( Y_SIZE + 2 )), ASSIGN_X + ASSIGN_WIDTH, ( INT16 )( (sYStart + 10) + ( sOffsetCounter + 1 ) * ( Y_SIZE + 2 )), MSYS_PRIORITY_NORMAL + 1, MSYS_NO_CURSOR, TeamListAssignmentRegionMvtCallBack, TeamListAssignmentRegionBtnCallBack ); // location region (same function as name regions, so uses the same callbacks) - MSYS_DefineRegion( &gTeamListLocationRegion[ sCounter ] , LOC_X, ( INT16 )( Y_START + ( sCounter ) * ( Y_SIZE + 2 ) + sYAdd ), LOC_X + LOC_WIDTH, ( INT16 )( 145 + ( sCounter + 1 ) * ( Y_SIZE + 2 ) + sYAdd ), MSYS_PRIORITY_NORMAL + 1, + MSYS_DefineRegion( &gTeamListLocationRegion[ sCounter ] , LOC_X, ( INT16 )( sYStart + ( sOffsetCounter ) * ( Y_SIZE + 2 )), LOC_X + LOC_WIDTH, ( INT16 )( (sYStart + 10) + ( sOffsetCounter + 1 ) * ( Y_SIZE + 2 )), MSYS_PRIORITY_NORMAL + 1, MSYS_NO_CURSOR, TeamListInfoRegionMvtCallBack, TeamListInfoRegionBtnCallBack ); // destination region - MSYS_DefineRegion( &gTeamListDestinationRegion[ sCounter ] ,DEST_ETA_X , ( INT16 )( Y_START + ( sCounter ) * ( Y_SIZE + 2 ) + sYAdd ), DEST_ETA_X + DEST_ETA_WIDTH, ( INT16 )( 145 + ( sCounter + 1 ) * ( Y_SIZE + 2 ) + sYAdd ), MSYS_PRIORITY_NORMAL + 1, + MSYS_DefineRegion( &gTeamListDestinationRegion[ sCounter ] ,DEST_ETA_X , ( INT16 )( sYStart + ( sOffsetCounter ) * ( Y_SIZE + 2 )), DEST_ETA_X + DEST_ETA_WIDTH, ( INT16 )( (sYStart + 10) + ( sOffsetCounter + 1 ) * ( Y_SIZE + 2 )), MSYS_PRIORITY_NORMAL + 1, MSYS_NO_CURSOR, TeamListDestinationRegionMvtCallBack, TeamListDestinationRegionBtnCallBack ); // contract region - MSYS_DefineRegion( &gTeamListContractRegion[ sCounter ] ,TIME_REMAINING_X , ( INT16 )( Y_START + ( sCounter ) * ( Y_SIZE + 2 ) + sYAdd), TIME_REMAINING_X + TIME_REMAINING_WIDTH, ( INT16 )( 145 + ( sCounter + 1 ) * ( Y_SIZE + 2 ) + sYAdd ), MSYS_PRIORITY_NORMAL + 1, + MSYS_DefineRegion( &gTeamListContractRegion[ sCounter ] ,TIME_REMAINING_X , ( INT16 )( sYStart + ( sOffsetCounter ) * ( Y_SIZE + 2 )), TIME_REMAINING_X + TIME_REMAINING_WIDTH, ( INT16 )( (sYStart + 10) + ( sOffsetCounter + 1 ) * ( Y_SIZE + 2 )), MSYS_PRIORITY_NORMAL + 1, MSYS_NO_CURSOR, TeamListContractRegionMvtCallBack, TeamListContractRegionBtnCallBack ); // contract region - MSYS_DefineRegion( &gTeamListSleepRegion[ sCounter ] ,SLEEP_X, ( INT16 )( Y_START + ( sCounter ) * ( Y_SIZE + 2 ) + sYAdd), SLEEP_X + SLEEP_WIDTH, ( INT16 )( 145 + ( sCounter + 1 ) * ( Y_SIZE + 2 ) + sYAdd ), MSYS_PRIORITY_NORMAL + 1, + MSYS_DefineRegion( &gTeamListSleepRegion[ sCounter ] ,SLEEP_X, ( INT16 )( sYStart + ( sOffsetCounter ) * ( Y_SIZE + 2 )), SLEEP_X + SLEEP_WIDTH, ( INT16 )( (sYStart + 10) + ( sOffsetCounter + 1 ) * ( Y_SIZE + 2 )), MSYS_PRIORITY_NORMAL + 1, MSYS_NO_CURSOR, TeamListSleepRegionMvtCallBack, TeamListSleepRegionBtnCallBack ); + + + //// name region + //MSYS_DefineRegion( &gTeamListNameRegion[ sCounter ] , NAME_X, ( INT16 )( Y_START + ( sCounter ) * ( Y_SIZE + 2 ) + sYAdd ), NAME_X + NAME_WIDTH, ( INT16 )( 145 + ( sCounter + 1 ) * ( Y_SIZE + 2 ) + sYAdd ), MSYS_PRIORITY_NORMAL, + // MSYS_NO_CURSOR, TeamListInfoRegionMvtCallBack, TeamListInfoRegionBtnCallBack ); + + //// assignment region + //MSYS_DefineRegion( &gTeamListAssignmentRegion[ sCounter ] ,ASSIGN_X , ( INT16 )( Y_START + ( sCounter ) * ( Y_SIZE + 2 ) + sYAdd), ASSIGN_X + ASSIGN_WIDTH, ( INT16 )( 145 + ( sCounter + 1 ) * ( Y_SIZE + 2 ) + sYAdd ), MSYS_PRIORITY_NORMAL + 1, + // MSYS_NO_CURSOR, TeamListAssignmentRegionMvtCallBack, TeamListAssignmentRegionBtnCallBack ); + + //// location region (same function as name regions, so uses the same callbacks) + //MSYS_DefineRegion( &gTeamListLocationRegion[ sCounter ] , LOC_X, ( INT16 )( Y_START + ( sCounter ) * ( Y_SIZE + 2 ) + sYAdd ), LOC_X + LOC_WIDTH, ( INT16 )( 145 + ( sCounter + 1 ) * ( Y_SIZE + 2 ) + sYAdd ), MSYS_PRIORITY_NORMAL + 1, + // MSYS_NO_CURSOR, TeamListInfoRegionMvtCallBack, TeamListInfoRegionBtnCallBack ); + + //// destination region + //MSYS_DefineRegion( &gTeamListDestinationRegion[ sCounter ] ,DEST_ETA_X , ( INT16 )( Y_START + ( sCounter ) * ( Y_SIZE + 2 ) + sYAdd ), DEST_ETA_X + DEST_ETA_WIDTH, ( INT16 )( 145 + ( sCounter + 1 ) * ( Y_SIZE + 2 ) + sYAdd ), MSYS_PRIORITY_NORMAL + 1, + // MSYS_NO_CURSOR, TeamListDestinationRegionMvtCallBack, TeamListDestinationRegionBtnCallBack ); + + //// contract region + //MSYS_DefineRegion( &gTeamListContractRegion[ sCounter ] ,TIME_REMAINING_X , ( INT16 )( Y_START + ( sCounter ) * ( Y_SIZE + 2 ) + sYAdd), TIME_REMAINING_X + TIME_REMAINING_WIDTH, ( INT16 )( 145 + ( sCounter + 1 ) * ( Y_SIZE + 2 ) + sYAdd ), MSYS_PRIORITY_NORMAL + 1, + // MSYS_NO_CURSOR, TeamListContractRegionMvtCallBack, TeamListContractRegionBtnCallBack ); + + //// contract region + //MSYS_DefineRegion( &gTeamListSleepRegion[ sCounter ] ,SLEEP_X, ( INT16 )( Y_START + ( sCounter ) * ( Y_SIZE + 2 ) + sYAdd), SLEEP_X + SLEEP_WIDTH, ( INT16 )( 145 + ( sCounter + 1 ) * ( Y_SIZE + 2 ) + sYAdd ), MSYS_PRIORITY_NORMAL + 1, + // MSYS_NO_CURSOR, TeamListSleepRegionMvtCallBack, TeamListSleepRegionBtnCallBack ); + MSYS_SetRegionUserData(&gTeamListNameRegion[sCounter],0,sCounter); MSYS_SetRegionUserData(&gTeamListAssignmentRegion[sCounter],0,sCounter); @@ -7480,7 +7624,7 @@ void CreateMouseRegionsForTeamList( void ) SetRegionFastHelpText( &gTeamListNameRegion[sCounter], pMapScreenMouseRegionHelpText[ 0 ] ); SetRegionFastHelpText( &gTeamListAssignmentRegion[sCounter], pMapScreenMouseRegionHelpText[ 1 ] ); SetRegionFastHelpText( &gTeamListSleepRegion[sCounter], pMapScreenMouseRegionHelpText[ 5 ] ); - SetRegionFastHelpText( &gTeamListLocationRegion[sCounter], pMapScreenMouseRegionHelpText[ 0 ] ); + SetRegionFastHelpText( &gTeamListLocationRegion[sCounter], pMapScreenMouseRegionHelpText[ 4 ] ); SetRegionFastHelpText( &gTeamListDestinationRegion[sCounter], pMapScreenMouseRegionHelpText[ 2 ] ); SetRegionFastHelpText( &gTeamListContractRegion[sCounter], pMapScreenMouseRegionHelpText[ 3 ] ); } @@ -8492,7 +8636,10 @@ void RenderMapRegionBackground( void ) MapscreenMarkButtonsDirty(); - RestoreExternBackgroundRect( 261, 0, 640 - 261, 359 ); + // WANNE 2 + //RestoreExternBackgroundRect( 261, 0, 379, 359 ); + + RestoreExternBackgroundRect( 261, 0, SCREEN_WIDTH - 261, SCREEN_HEIGHT - 121 ); // don't bother if showing sector inventory instead of the map!!! if( !fShowMapInventoryPool ) @@ -8562,7 +8709,9 @@ void RenderTeamRegionBackground( void ) MarkAllBoxesAsAltered( ); // restore background for area - RestoreExternBackgroundRect( 0, 107, 261 - 0, 359 - 107 ); + + // WANNE 2 + RestoreExternBackgroundRect( 0, 107, 261, SCREEN_HEIGHT - 106 - 121 ); MapscreenMarkButtonsDirty(); @@ -10183,8 +10332,20 @@ BOOLEAN HandlePreloadOfMapGraphics( void ) /*strcpy(vs_desc.ImageFile, "INTERFACE\\playlist3.pcx"); CHECKF(AddVideoSurface( &vs_desc, &guiCHARLIST ));*/ + // WANNE 2 VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; - FilenameForBPP("INTERFACE\\newgoldpiece3.sti", VObjectDesc.ImageFile ); + if (iResolution == 0) + { + FilenameForBPP("INTERFACE\\newgoldpiece3.sti", VObjectDesc.ImageFile ); + } + else if (iResolution == 1) + { + FilenameForBPP("INTERFACE\\newgoldpiece3_800x600.sti", VObjectDesc.ImageFile ); + } + else if (iResolution == 2) + { + FilenameForBPP("INTERFACE\\newgoldpiece3_1024x768.sti", VObjectDesc.ImageFile ); + } CHECKF(AddVideoObject(&VObjectDesc, &guiCHARLIST)); //VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; @@ -10494,6 +10655,106 @@ void NextInventoryMapBtnCallback( GUI_BUTTON *btn, INT32 reason ) } } +// WANNE 2 +//void BtnMercsUpMapScreenCallback( GUI_BUTTON *btn,INT32 reason ) +//{ +// // WANNE 2 -> see Map Screen Interface Bottom Line 766 (BtnMessageUpMapScreenCallback) +// int i = 10; +//} +// +//void BtnMercsDownMapScreenCallback( GUI_BUTTON *btn,INT32 reason ) +//{ +// // WANNE 2 -> see Map Screen Interface Bottom Line 766 (BtnMessageUpMapScreenCallback) +// int i = 10; +//} +// +//void BtnVehicleUpMapScreenCallback( GUI_BUTTON *btn,INT32 reason ) +//{ +// // WANNE 2 -> see Map Screen Interface Bottom Line 766 (BtnMessageUpMapScreenCallback) +// int i = 10; +//} +// +//void BtnVehicleDownMapScreenCallback( GUI_BUTTON *btn,INT32 reason ) +//{ +// // WANNE 2 -> see Map Screen Interface Bottom Line 766 (BtnMessageUpMapScreenCallback) +// int i = 10; +//} + +// WANNE 2 +//void DeleteButtonsForScrolling(void) +//{ +// if (fScrollButtonsInitialized == TRUE) +// { +// // mercs scroll buttons +// RemoveButton( guiMapMercsScrollButtons[ 0 ]); +// RemoveButton( guiMapMercsScrollButtons[ 1 ]); +// UnloadButtonImage( guiMapMercsScrollButtonsImage[ 0 ] ); +// UnloadButtonImage( guiMapMercsScrollButtonsImage[ 1 ] ); +// +// RemoveButton( guiMapVehicleScrollButtons[ 0 ]); +// RemoveButton( guiMapVehicleScrollButtons[ 1 ]); +// UnloadButtonImage( guiMapVehicleScrollButtonsImage[ 0 ] ); +// UnloadButtonImage( guiMapVehicleScrollButtonsImage[ 1 ] ); +// +// fScrollButtonsInitialized = FALSE; +// } +//} + +// WANNE 2 +// Create the scrolling arrows +//void CreateButtonsForScrolling( void ) +//{ +// if (fScrollButtonsInitialized == FALSE) +// { +// INT32 iXPos = 247; +// INT32 iMercUpY = -1; +// INT32 iVehicleUpY = -1; +// +// if (iResolution == 0) +// { +// iMercUpY = 207; +// iVehicleUpY = 321; +// } +// else if (iResolution == 1) +// { +// iMercUpY = 256; +// iVehicleUpY = 429; +// } +// else if (iResolution == 2) +// { +// iMercUpY = 328; +// iVehicleUpY = 579; +// } +// +// // merc - scroll up +// guiMapMercsScrollButtonsImage[ MAP_SCROLL_MERCS_UP ]= LoadButtonImage( "INTERFACE\\map_screen_bottom_arrows.sti" ,11,4,-1,6,-1 ); +// guiMapMercsScrollButtons[ MAP_SCROLL_MERCS_UP ] = QuickCreateButton( guiMapMercsScrollButtonsImage[ MAP_SCROLL_MERCS_UP ], iXPos, iMercUpY, +// BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, +// (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnMercsUpMapScreenCallback); +// +// // merc - scroll down +// guiMapMercsScrollButtonsImage[ MAP_SCROLL_MERCS_DOWN ]= LoadButtonImage( "INTERFACE\\map_screen_bottom_arrows.sti" ,12,5,-1,7,-1 ); +// guiMapMercsScrollButtons[ MAP_SCROLL_MERCS_DOWN ] = QuickCreateButton( guiMapMercsScrollButtonsImage[ MAP_SCROLL_MERCS_DOWN ], iXPos, iMercUpY + 17, +// BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, +// (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnMercsDownMapScreenCallback); +// +// // vehicle - scroll up +// guiMapVehicleScrollButtonsImage[ MAP_SCROLL_VEHICLE_UP ]= LoadButtonImage( "INTERFACE\\map_screen_bottom_arrows.sti" ,11,4,-1,6,-1 ); +// guiMapVehicleScrollButtons[ MAP_SCROLL_VEHICLE_UP ] = QuickCreateButton( guiMapVehicleScrollButtonsImage[ MAP_SCROLL_VEHICLE_UP ], iXPos, iVehicleUpY, +// BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, +// (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnVehicleUpMapScreenCallback); +// +// // vehicle - scroll down +// guiMapVehicleScrollButtonsImage[ MAP_SCROLL_VEHICLE_DOWN ]= LoadButtonImage( "INTERFACE\\map_screen_bottom_arrows.sti" ,12,5,-1,7,-1 ); +// guiMapVehicleScrollButtons[ MAP_SCROLL_VEHICLE_DOWN ] = QuickCreateButton( guiMapVehicleScrollButtonsImage[ MAP_SCROLL_VEHICLE_DOWN ], iXPos, iVehicleUpY + 17, +// BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, +// (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnVehicleDownMapScreenCallback); +// +// fScrollButtonsInitialized = TRUE; +// } +//} + + void CreateDestroyMapCharacterScrollButtons( void ) { static BOOLEAN fCreated = FALSE; @@ -11072,7 +11333,9 @@ void DisplayIconsForMercsAsleep( void ) pSoldier = MercPtrs[ gCharactersList[ iCounter ].usSolID ]; if( pSoldier->bActive && pSoldier->fMercAsleep && CanChangeSleepStatusForSoldier( pSoldier ) ) { - BltVideoObject( guiSAVEBUFFER , hHandle, 0, 125, ( INT16 )( Y_START+(iCounter * ( Y_SIZE + 2 ) ) ) , VO_BLT_SRCTRANSPARENCY,NULL ); + // WANNE 2 + //BltVideoObject( guiSAVEBUFFER , hHandle, 0, 125, ( INT16 )( Y_START+(iCounter * ( Y_SIZE + 2 ) ) ) , VO_BLT_SRCTRANSPARENCY,NULL ); + BltVideoObject( guiSAVEBUFFER , hHandle, 0, SLEEP_X + 2, ( INT16 )( Y_START+(iCounter * ( Y_SIZE + 2 ) ) ) , VO_BLT_SRCTRANSPARENCY,NULL ); } } } @@ -11088,25 +11351,30 @@ void CheckForAndRenderNewMailOverlay() { if( GetJA2Clock() % 1000 < 667 ) { + // WANNE 2 if( ButtonList[ guiMapBottomExitButtons[ MAP_EXIT_TO_LAPTOP ] ]->uiFlags & BUTTON_CLICKED_ON ) { //button is down, so offset the icon - BltVideoObjectFromIndex( FRAME_BUFFER, guiNewMailIcons, 1, 465, 418, VO_BLT_SRCTRANSPARENCY, NULL ); - InvalidateRegion( 465, 418, 480, 428 ); + //BltVideoObjectFromIndex( FRAME_BUFFER, guiNewMailIcons, 1, 465, 418, VO_BLT_SRCTRANSPARENCY, NULL ); + BltVideoObjectFromIndex( FRAME_BUFFER, guiNewMailIcons, 1, (SCREEN_WIDTH - 175), (SCREEN_HEIGHT - 62), VO_BLT_SRCTRANSPARENCY, NULL ); + //InvalidateRegion( 465, 418, 480, 428 ); + InvalidateRegion( (SCREEN_WIDTH - 175), (SCREEN_HEIGHT - 62), (SCREEN_WIDTH - 160), (SCREEN_HEIGHT - 52 )); } + // WANNE 2 else - { //button is up, so draw the icon normally - BltVideoObjectFromIndex( FRAME_BUFFER, guiNewMailIcons, 0, 464, 417, VO_BLT_SRCTRANSPARENCY, NULL ); + { //button is up, so draw the icon normally + //BltVideoObjectFromIndex( FRAME_BUFFER, guiNewMailIcons, 0, 464, 417, VO_BLT_SRCTRANSPARENCY, NULL ); + BltVideoObjectFromIndex( FRAME_BUFFER, guiNewMailIcons, 0, (SCREEN_WIDTH - 176), (SCREEN_HEIGHT - 63), VO_BLT_SRCTRANSPARENCY, NULL ); if( !(ButtonList[ guiMapBottomExitButtons[ MAP_EXIT_TO_LAPTOP ] ]->uiFlags & BUTTON_ENABLED ) ) { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; - SGPRect area = { 463, 417, 477, 425 }; + SGPRect area = { (SCREEN_WIDTH - 177), (SCREEN_HEIGHT - 63), (SCREEN_WIDTH - 163), (SCREEN_HEIGHT - 55) }; pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); Blt16BPPBufferHatchRect( (UINT16*)pDestBuf, uiDestPitchBYTES, &area ); UnLockVideoSurface( FRAME_BUFFER ); } - InvalidateRegion( 463, 417, 481, 430 ); + InvalidateRegion( (SCREEN_WIDTH - 177), (SCREEN_HEIGHT - 63), (SCREEN_WIDTH - 159), (SCREEN_HEIGHT - 50) ); } } diff --git a/Strategic/strategicmap.cpp b/Strategic/strategicmap.cpp index 52ae941e..19c71b03 100644 --- a/Strategic/strategicmap.cpp +++ b/Strategic/strategicmap.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #include "Loading Screen.h" @@ -773,6 +774,7 @@ UINT32 UndergroundTacticalTraversalTime( INT8 bExitDirection ) return 0xffffffff; } +// WANNE 2 void BeginLoadScreen( void ) { SGPRect SrcRect, DstRect; @@ -788,13 +790,14 @@ void BeginLoadScreen( void ) { DstRect.iLeft = 0; DstRect.iTop = 0; - DstRect.iRight = 640; - DstRect.iBottom = 480; + DstRect.iRight = SCREEN_WIDTH; + DstRect.iBottom = SCREEN_HEIGHT; uiTimeRange = 2000; iPercentage = 0; iLastShadePercentage = 0; uiStartTime = GetJA2Clock(); - BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 0, 0, 640, 480 ); + + BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); PlayJA2SampleFromFile( "SOUNDS\\Final Psionic Blast 01 (16-44).wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN ); while( iPercentage < 100 ) { @@ -811,31 +814,21 @@ void BeginLoadScreen( void ) if( iPercentage > 50 ) { - //iFactor = (iPercentage - 50) * 2; - //if( iFactor > iLastShadePercentage ) - // { - //Calculate the difference from last shade % to the new one. Ex: Going from - //50% shade value to 60% shade value requires applying 20% to the 50% to achieve 60%. - //if( iLastShadePercentage ) - // iReqShadePercentage = 100 - (iFactor * 100 / iLastShadePercentage); - //else - // iReqShadePercentage = iFactor; - //Record the new final shade percentage. - //iLastShadePercentage = iFactor; - ShadowVideoSurfaceRectUsingLowPercentTable( guiSAVEBUFFER, 0, 0, 640, 480 ); - // } + ShadowVideoSurfaceRectUsingLowPercentTable( guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); } SrcRect.iLeft = 536 * iPercentage / 100; - SrcRect.iRight = 640 - iPercentage / 20; + SrcRect.iRight = SCREEN_WIDTH - iPercentage / 20; SrcRect.iTop = 367 * iPercentage / 100; - SrcRect.iBottom = 480 - 39 * iPercentage / 100; + SrcRect.iBottom = SCREEN_HEIGHT - 39 * iPercentage / 100; + BltStretchVideoSurface( FRAME_BUFFER, guiSAVEBUFFER, 0, 0, 0, &SrcRect, &DstRect ); InvalidateScreen(); RefreshScreen( NULL ); } } - ColorFillVideoSurfaceArea( FRAME_BUFFER, 0, 0, 640, 480, Get16BPPColor( FROMRGB( 0, 0, 0 ) ) ); + + ColorFillVideoSurfaceArea( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, Get16BPPColor( FROMRGB( 0, 0, 0 ) ) ); InvalidateScreen( ); RefreshScreen( NULL ); diff --git a/Tactical/Auto Bandage.cpp b/Tactical/Auto Bandage.cpp index eb20a8da..c6c57916 100644 --- a/Tactical/Auto Bandage.cpp +++ b/Tactical/Auto Bandage.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #else @@ -430,10 +431,11 @@ void AutoBandage( BOOLEAN fStart ) giBoxId = PrepareMercPopupBox( -1, DIALOG_MERC_POPUP_BACKGROUND, DIALOG_MERC_POPUP_BORDER, sAutoBandageString, 200, 40, 10, 30, &gusTextBoxWidth, &gusTextBoxHeight ); } + // WANNE 2 aRect.iTop = 0; aRect.iLeft = 0; aRect.iBottom = INV_INTERFACE_START_Y; - aRect.iRight = 640; + aRect.iRight = SCREEN_WIDTH; // Determine position ( centered in rect ) gsX = (INT16)( ( ( ( aRect.iRight - aRect.iLeft ) - gusTextBoxWidth ) / 2 ) + aRect.iLeft ); @@ -725,8 +727,9 @@ void DisplayAutoBandageUpdatePanel( void ) iTotalPixelsWide = TACT_UPDATE_MERC_FACE_X_WIDTH * iNumberDoctorsWide; + // WANNE 2 // now get the x and y position for the box - sXPosition = ( 640 - iTotalPixelsWide ) / 2; + sXPosition = ( SCREEN_WIDTH - iTotalPixelsWide ) / 2; sYPosition = ( INV_INTERFACE_START_Y - iTotalPixelsHigh ) / 2; diff --git a/Tactical/Campaign.cpp b/Tactical/Campaign.cpp index 81a08503..06cf8f6b 100644 --- a/Tactical/Campaign.cpp +++ b/Tactical/Campaign.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #else @@ -60,8 +61,12 @@ UINT8 CalcImportantSectorControl( void ); // give pSoldier usNumChances to improve ubStat. If it's from training, it doesn't count towards experience level gain void StatChange(SOLDIERTYPE *pSoldier, UINT8 ubStat, UINT16 usNumChances, UINT8 ubReason) { - Assert(pSoldier != NULL); - Assert(pSoldier->bActive); + // WANNE 2 + if (pSoldier == NULL || pSoldier->bActive == FALSE) + return; // THIS SHOULD NEVER HAPPEN + + //Assert(pSoldier != NULL); + //Assert(pSoldier->bActive); // ignore non-player soldiers if (!PTR_OURTEAM) diff --git a/Tactical/Civ Quotes.cpp b/Tactical/Civ Quotes.cpp index 613c3eca..3f2fef28 100644 --- a/Tactical/Civ Quotes.cpp +++ b/Tactical/Civ Quotes.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #endif @@ -380,9 +381,9 @@ void BeginCivQuote( SOLDIERTYPE *pCiv, UINT8 ubCivQuoteID, UINT8 ubEntryID, INT1 } // CHECK FOR LEFT/RIGHT - if ( ( sX + gusCivQuoteBoxWidth ) > 640 ) + if ( ( sX + gusCivQuoteBoxWidth ) > SCREEN_WIDTH ) { - sX = 640 - gusCivQuoteBoxWidth; + sX = SCREEN_WIDTH - gusCivQuoteBoxWidth; } // Now check for top @@ -392,9 +393,9 @@ void BeginCivQuote( SOLDIERTYPE *pCiv, UINT8 ubCivQuoteID, UINT8 ubEntryID, INT1 } // Check for bottom - if ( ( sY + gusCivQuoteBoxHeight ) > 340 ) + if ( ( sY + gusCivQuoteBoxHeight ) > (SCREEN_HEIGHT - INV_INTERFACE_HEIGHT)) { - sY = 340 - gusCivQuoteBoxHeight; + sY = (SCREEN_HEIGHT - INV_INTERFACE_HEIGHT) - gusCivQuoteBoxHeight; } } diff --git a/Tactical/Dialogue Control.cpp b/Tactical/Dialogue Control.cpp index 7c746f19..2159ceec 100644 --- a/Tactical/Dialogue Control.cpp +++ b/Tactical/Dialogue Control.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #include "PreBattle Interface.h" @@ -1977,6 +1978,8 @@ void ExecuteTacticalTextBox( INT16 sLeftPosition, STR16 pString ) VIDEO_OVERLAY_DESC VideoOverlayDesc; // check if mouse region created, if so, do not recreate + + // WANNE 2 if( fTextBoxMouseRegionCreated == TRUE ) { return; @@ -2003,6 +2006,12 @@ void ExecuteTacticalTextBox( INT16 sLeftPosition, STR16 pString ) gsTopPosition = 20; + // WANNE 2 + //if( fTextBoxMouseRegionCreated == TRUE ) + //{ + // return; + //} + //Define main region MSYS_DefineRegion( &gTextBoxMouseRegion, VideoOverlayDesc.sLeft, VideoOverlayDesc.sTop, VideoOverlayDesc.sRight, VideoOverlayDesc.sBottom, MSYS_PRIORITY_HIGHEST, CURSOR_NORMAL, MSYS_NO_CALLBACK, TextOverlayClickCallback ); diff --git a/Tactical/DisplayCover.cpp b/Tactical/DisplayCover.cpp index aac153c3..e70c02f1 100644 --- a/Tactical/DisplayCover.cpp +++ b/Tactical/DisplayCover.cpp @@ -434,7 +434,7 @@ INT8 CalcCoverForGridNoBasedOnTeamKnownEnemies( SOLDIERTYPE *pSoldier, INT16 sTa } usRange = (UINT16)GetRangeInCellCoordsFromGridNoDiff( pOpponent->sGridNo, sTargetGridNo ); - usSightLimit = DistanceVisible( pOpponent, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sTargetGridNo, pSoldier->bLevel ); + usSightLimit = DistanceVisible( pOpponent, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sTargetGridNo, pSoldier->bLevel, pSoldier ); if( usRange > ( usSightLimit * CELL_X_SIZE ) ) { @@ -933,7 +933,7 @@ INT8 CalcIfSoldierCanSeeGridNo( SOLDIERTYPE *pSoldier, INT16 sTargetGridNo, BOOL } - usSightLimit = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sTargetGridNo, fRoof ); + usSightLimit = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sTargetGridNo, fRoof, pSoldier ); // // Prone diff --git a/Tactical/End Game.cpp b/Tactical/End Game.cpp index bc265fc3..e1faf0d5 100644 --- a/Tactical/End Game.cpp +++ b/Tactical/End Game.cpp @@ -163,7 +163,7 @@ void HandleDeidrannaDeath( SOLDIERTYPE *pKillerSoldier, INT16 sGridNo, INT8 bLev if ( QuoteExp_WitnessDeidrannaDeath[ pTeamSoldier->ubProfile ] ) { // Can we see location? - sDistVisible = DistanceVisible( pTeamSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel ); + sDistVisible = DistanceVisible( pTeamSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel, pTeamSoldier ); if ( SoldierTo3DLocationLineOfSightTest( pTeamSoldier, sGridNo, bLevel, 3, (UINT8) sDistVisible, TRUE ) ) { @@ -454,7 +454,7 @@ void HandleQueenBitchDeath( SOLDIERTYPE *pKillerSoldier, INT16 sGridNo, INT8 bLe if ( QuoteExp_WitnessQueenBugDeath[ pTeamSoldier->ubProfile ] ) { // Can we see location? - sDistVisible = DistanceVisible( pTeamSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel ); + sDistVisible = DistanceVisible( pTeamSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel, pTeamSoldier ); if ( SoldierTo3DLocationLineOfSightTest( pTeamSoldier, sGridNo, bLevel, 3, (UINT8) sDistVisible, TRUE ) ) { diff --git a/Tactical/Handle Items.cpp b/Tactical/Handle Items.cpp index dfb10704..242f4896 100644 --- a/Tactical/Handle Items.cpp +++ b/Tactical/Handle Items.cpp @@ -452,7 +452,12 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, UINT16 usGridNo, INT8 bLevel, UINT16 us DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleItem: auto fire - setting dice sides, marksmanship = %d",pSoldier->bMarksmanship)); //UINT32 diceSides = RAND_MAX; //Madd: tried to make this more marksmanship dependent than agility, a level 10 auto-weapons specialist with 100 in all stats was wasting wayyy too many APs on this fucker - UINT32 diceSides = RAND_MAX / ( max(1,pSoldier->bMarksmanship) / 10) ; + //UINT32 diceSides = RAND_MAX / ( max(1,pSoldier->bMarksmanship) / 10) ; + + //Kaiden: Had to change the minimum value to 10 instead of 1, + //Rounding down resulted in division by zero and caused a crash. + UINT32 diceSides = RAND_MAX / ( max(10,pSoldier->bMarksmanship) / 10) ; + DOUBLE avgAPadded = max(((400.0f-2.0f*pSoldier->bAgility))*(63.0f-5.0f*(pSoldier->bExpLevel+2.0f*NUM_SKILL_TRAITS( pSoldier, AUTO_WEAPS )))/2700.0f,1); //Important! don't make this zero, the formulae don't like it. UINT32 chanceToMisfire = (UINT32)(((DOUBLE)diceSides*(2.0f*avgAPadded+1.0f-sqrt(4.0f*avgAPadded+1.0f)))/(2.0f*avgAPadded)); //derive the chace to misfire from the desired average AP overspent, derived suing UINT32 chanceToMisfireDry = (UINT32)(((DOUBLE)diceSides*(avgAPadded+1.0f-sqrt(2.0f*avgAPadded+1.0f)))/(avgAPadded)); //chance to misfire if weapon is dry. Designed to waste avgAPadded/2 APs @@ -4973,7 +4978,7 @@ void TestPotentialOwner( SOLDIERTYPE * pSoldier ) { if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->bLife >= OKLIFE ) { - if ( SoldierToSoldierLineOfSightTest( pSoldier, gpTempSoldier, (UINT8) DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, 0, gpTempSoldier->sGridNo, gpTempSoldier->bLevel ), TRUE ) ) + if ( SoldierToSoldierLineOfSightTest( pSoldier, gpTempSoldier, (UINT8) DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, 0, gpTempSoldier->sGridNo, gpTempSoldier->bLevel, gpTempSoldier ), TRUE ) ) { MakeNPCGrumpyForMinorOffense( pSoldier, gpTempSoldier ); } diff --git a/Tactical/Handle UI.cpp b/Tactical/Handle UI.cpp index 14eea991..afbba3c5 100644 --- a/Tactical/Handle UI.cpp +++ b/Tactical/Handle UI.cpp @@ -4669,7 +4669,7 @@ UINT32 UIHandleTOnTerrain( UI_EVENT *pUIEvent ) //ATE: Check if we have good LOS // is he close enough to see that gridno if he turns his head? - sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sTargetGridNo, pSoldier->bLevel ); + sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sTargetGridNo, pSoldier->bLevel, pSoldier ); if ( uiRange <= NPC_TALK_RADIUS ) @@ -5484,7 +5484,7 @@ BOOLEAN HandleTalkInit( ) { //ATE: Check if we have good LOS // is he close enough to see that gridno if he turns his head? - sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, pTSoldier->sGridNo, pTSoldier->bLevel ); + sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, pTSoldier->sGridNo, pTSoldier->bLevel, pTSoldier ); // Check LOS! if ( !SoldierTo3DLocationLineOfSightTest( pSoldier, pTSoldier->sGridNo, pTSoldier->bLevel, 3, (UINT8) sDistVisible, TRUE ) ) @@ -6150,7 +6150,7 @@ BOOLEAN ValidQuickExchangePosition( ) if ( PythSpacesAway( pSoldier->sGridNo, pOverSoldier->sGridNo ) == 1 ) { // Check if we have LOS to them.... - sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, pOverSoldier->sGridNo, pOverSoldier->bLevel ); + sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, pOverSoldier->sGridNo, pOverSoldier->bLevel, pOverSoldier ); if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pOverSoldier->sGridNo, pOverSoldier->bLevel, (UINT8)3, (UINT8) sDistVisible, TRUE ) ) { diff --git a/Tactical/Interface Items.cpp b/Tactical/Interface Items.cpp index ebd64a4d..3ea6e414 100644 --- a/Tactical/Interface Items.cpp +++ b/Tactical/Interface Items.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #include "language defines.h" @@ -1062,37 +1063,6 @@ void INVRenderINVPanelItem( SOLDIERTYPE *pSoldier, INT16 sPocket, UINT8 fDirtyLe { // CHECK FOR COMPATIBILITY WITH MAGAZINES -/* OLD VERSION OF GUN/AMMO MATCH HIGHLIGHTING - UINT32 uiDestPitchBYTES; - UINT8 *pDestBuf; - UINT16 usLineColor; - - if ( ( Item [ pSoldier->inv[ HANDPOS ].usItem ].usItemClass & IC_GUN ) && ( Item[ pObject->usItem ].usItemClass & IC_AMMO ) ) - { - // CHECK - if (Weapon[pSoldier->inv[ HANDPOS ].usItem].ubCalibre == Magazine[Item[pObject->usItem].ubClassIndex].ubCalibre ) - { - // IT's an OK calibre ammo, do something! - // Render Item with specific color - //fOutline = TRUE; - //sOutlineColor = Get16BPPColor( FROMRGB( 96, 104, 128 ) ); - //sOutlineColor = Get16BPPColor( FROMRGB( 20, 20, 120 ) ); - - // Draw rectangle! - pDestBuf = LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES ); - SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, 640, 480 ); - - //usLineColor = Get16BPPColor( FROMRGB( 255, 255, 0 ) ); - usLineColor = Get16BPPColor( FROMRGB( 230, 215, 196 ) ); - RectangleDraw( TRUE, (sX+1), (sY+1), (sX + gSMInvData[ sPocket ].sWidth - 2 ),( sY + gSMInvData[ sPocket ].sHeight - 2 ), usLineColor, pDestBuf ); - - SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, 640, 480 ); - - UnLockVideoSurface( guiSAVEBUFFER ); - } - } -*/ - if ( gbCompatibleAmmo[ sPocket ] ) { fOutline = TRUE; @@ -4913,7 +4883,7 @@ BOOLEAN HandleItemPointerClick( UINT16 usMapPos ) return( FALSE ); } - sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, gpItemPointerSoldier->sGridNo, gpItemPointerSoldier->bLevel ); + sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, gpItemPointerSoldier->sGridNo, gpItemPointerSoldier->bLevel, gpItemPointerSoldier ); // Check LOS.... if ( !SoldierTo3DLocationLineOfSightTest( pSoldier, gpItemPointerSoldier->sGridNo, gpItemPointerSoldier->bLevel, 3, (UINT8) sDistVisible, TRUE ) ) @@ -7221,15 +7191,34 @@ void GetHelpTextForItem( INT16 * pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldi } else if ( usItem != NOTHING ) { - if ( !gGameOptions.fGunNut && Item[ usItem ].usItemClass == IC_GUN && !Item[usItem].rocketlauncher && !Item[usItem].rocketrifle ) + // Retrieve the status of the items + // Find the minimum status value - not just the first one + INT16 sValue = pObject->bStatus[ 0 ]; + INT16 i; + for(i = 1; i < pObject->ubNumberOfObjects; i++) { - swprintf( (wchar_t *)pStr, L"%s (%s)", ItemNames[ usItem ], AmmoCaliber[ Weapon[ usItem ].ubCalibre ] ); - } - else - { - swprintf( (wchar_t *)pStr, L"%s", ItemNames[ usItem ] ); + if(pObject->bStatus[ i ] < sValue) + { + sValue = pObject->bStatus[ i ]; + } } + // The first tool tip is for rocket rifles + if ( !gGameOptions.fGunNut && Item[ usItem ].usItemClass == IC_GUN && !Item[usItem].rocketlauncher && !Item[usItem].rocketrifle ) + { + swprintf( (wchar_t *)pStr, L"%s (%s) [%d%%]", ItemNames[ usItem ], AmmoCaliber[ Weapon[ usItem ].ubCalibre ], sValue ); + } + // The next is for ammunition which gets the measurement 'rnds' + else if (Item[ usItem ].usItemClass == IC_AMMO) + { + swprintf( (wchar_t *)pStr, L"%s [%d rnds]", ItemNames[ usItem ], sValue ); + } + // The final, and typical case, is that of an item with a percent status + else + { + swprintf( (wchar_t *)pStr, L"%s [%d%%]", ItemNames[ usItem ], sValue ); + } + if ( ( Item[pObject->usItem].fingerprintid ) && pObject->ubImprintID < NO_PROFILE ) { INT16 pStr2[20]; @@ -7531,9 +7520,10 @@ BOOLEAN InitializeStealItemPickupMenu( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOppo } // CHECK FOR LEFT/RIGHT - if ( ( sX + gItemPickupMenu.sWidth ) > 640 ) + // WANNE 2 + if ( ( sX + gItemPickupMenu.sWidth ) > SCREEN_WIDTH ) { - sX = 640 - gItemPickupMenu.sWidth - ITEMPICK_START_X_OFFSET; + sX = SCREEN_WIDTH - gItemPickupMenu.sWidth - ITEMPICK_START_X_OFFSET; } else { @@ -7552,9 +7542,10 @@ BOOLEAN InitializeStealItemPickupMenu( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOppo } // Check for bottom - if ( ( sY + gItemPickupMenu.sHeight ) > 340 ) + // WANNE 2 + if ( ( sY + gItemPickupMenu.sHeight ) > (SCREEN_HEIGHT - INV_INTERFACE_HEIGHT) ) { - sY = 340 - gItemPickupMenu.sHeight; + sY = (SCREEN_HEIGHT - INV_INTERFACE_HEIGHT) - gItemPickupMenu.sHeight; } } @@ -7580,8 +7571,14 @@ BOOLEAN InitializeStealItemPickupMenu( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOppo // Build a mouse region here that is over any others..... - MSYS_DefineRegion( &(gItemPickupMenu.BackRegion ), (INT16)( 532 ), (INT16)( 367 ), (INT16)( 640 ),(INT16)( 480 ), MSYS_PRIORITY_HIGHEST, + /*MSYS_DefineRegion( &(gItemPickupMenu.BackRegion ), (INT16)( 532 ), (INT16)( 367 ), (INT16)( 640 ),(INT16)( 480 ), MSYS_PRIORITY_HIGHEST, + CURSOR_NORMAL, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK ); */ + + // WANNE 2 + // Build a mouse region here that is over any others..... + MSYS_DefineRegion( &(gItemPickupMenu.BackRegion ), (INT16)( iScreenWidthOffset + 532 ), (INT16)( iScreenHeightOffset + 367 ), (INT16)( SCREEN_WIDTH ),(INT16)( SCREEN_HEIGHT ), MSYS_PRIORITY_HIGHEST, CURSOR_NORMAL, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK ); + // Add region MSYS_AddRegion( &(gItemPickupMenu.BackRegion ) ); diff --git a/Tactical/Interface Panels.cpp b/Tactical/Interface Panels.cpp index d96430ed..11aef347 100644 --- a/Tactical/Interface Panels.cpp +++ b/Tactical/Interface Panels.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #else @@ -312,7 +313,7 @@ int INTERFACE_CLOCK_X; int INTERFACE_CLOCK_Y; int LOCATION_NAME_X; int LOCATION_NAME_Y; - + typedef enum { @@ -561,7 +562,7 @@ void CheckForDisabledForGiveItem( ) { sDist = PythSpacesAway( gpSMCurrentMerc->sGridNo, pSoldier->sGridNo ); - sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, gpSMCurrentMerc->sGridNo, gpSMCurrentMerc->bLevel ); + sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, gpSMCurrentMerc->sGridNo, gpSMCurrentMerc->bLevel, gpSMCurrentMerc ); // Check LOS.... if ( SoldierTo3DLocationLineOfSightTest( pSoldier, gpSMCurrentMerc->sGridNo, gpSMCurrentMerc->bLevel, 3, (UINT8) sDistVisible, TRUE ) ) @@ -596,7 +597,7 @@ void CheckForDisabledForGiveItem( ) sDist = PythSpacesAway( MercPtrs[ ubSrcSoldier ]->sGridNo, sDestGridNo ); // is he close enough to see that gridno if he turns his head? - sDistVisible = DistanceVisible( MercPtrs[ ubSrcSoldier ], DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sDestGridNo, bDestLevel ); + sDistVisible = DistanceVisible( MercPtrs[ ubSrcSoldier ], DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sDestGridNo, bDestLevel, MercPtrs[ ubSrcSoldier ] ); // Check LOS.... if ( SoldierTo3DLocationLineOfSightTest( MercPtrs[ ubSrcSoldier ], sDestGridNo, bDestLevel, 3, (UINT8) sDistVisible, TRUE ) ) @@ -1316,9 +1317,11 @@ BOOLEAN InitializeSMPanelCoords( ) SM_LOOKB_Y = ( 108 + INV_INTERFACE_START_Y ); SM_STEALTHMODE_X = ( 187 + INTERFACE_START_X ); SM_STEALTHMODE_Y = ( 73 + INV_INTERFACE_START_Y ); - SM_DONE_X = ( 543 + INTERFACE_START_X ); + + // WANNE 2 + SM_DONE_X = (SCREEN_WIDTH - 97);//( 543 + INTERFACE_START_X ); SM_DONE_Y = ( 4 + INV_INTERFACE_START_Y ); - SM_MAPSCREEN_X = ( 589 + INTERFACE_START_X ); + SM_MAPSCREEN_X = (SCREEN_WIDTH - 51);//( 589 + INTERFACE_START_X ); SM_MAPSCREEN_Y = ( 4 + INV_INTERFACE_START_Y ); SM_POSITIONB_X = ( 106 + INTERFACE_START_X ); @@ -1382,9 +1385,9 @@ BOOLEAN InitializeSMPanelCoords( ) STATS_TEXT_FONT_COLOR = 5; // ow and te clock and location i will put it here - INTERFACE_CLOCK_X = ( 554 + INTERFACE_START_X ); + INTERFACE_CLOCK_X = (SCREEN_WIDTH - 86); //( 554 + INTERFACE_START_X ); INTERFACE_CLOCK_Y = ( 119 + INV_INTERFACE_START_Y ); - LOCATION_NAME_X = ( 548 + INTERFACE_START_X ); + LOCATION_NAME_X = (SCREEN_WIDTH - 92); //( 548 + INTERFACE_START_X ); LOCATION_NAME_Y = ( 65 + INTERFACE_START_Y ); // so we got everything "dynamic" now we just return TRUE @@ -3486,6 +3489,7 @@ void BtnPositionShowCallback(GUI_BUTTON *btn,INT32 reason) } +// WANNE 2 BOOLEAN InitializeTEAMPanelCoords( ) { @@ -3494,11 +3498,12 @@ BOOLEAN InitializeTEAMPanelCoords( ) TM_APPANEL_HEIGHT = 56; TM_APPANEL_WIDTH = 16; - TM_ENDTURN_X = ( 507 + INTERFACE_START_X ); + // WANNE 2 + TM_ENDTURN_X = (SCREEN_WIDTH - 133); //( 507 + INTERFACE_START_X ); TM_ENDTURN_Y = ( 9 + INTERFACE_START_Y ); - TM_ROSTERMODE_X = ( 507 + INTERFACE_START_X ); + TM_ROSTERMODE_X = (SCREEN_WIDTH - 133); //( 507 + INTERFACE_START_X ); TM_ROSTERMODE_Y = ( 45 + INTERFACE_START_Y ); - TM_DISK_X = ( 507 + INTERFACE_START_X ); + TM_DISK_X = (SCREEN_WIDTH - 133); //( 507 + INTERFACE_START_X ); TM_DISK_Y = ( 81 + INTERFACE_START_Y ); TM_NAME_WIDTH = 60; @@ -3606,6 +3611,9 @@ BOOLEAN InitializeTEAMPanel( ) UINT32 cnt, posIndex; static BOOLEAN fFirstTime = TRUE; + // WANNE 2 + fDisplayOverheadMap = TRUE; + /* OK i need to initialize coords here * Isnt it cool * any questions? joker @@ -3716,6 +3724,7 @@ BOOLEAN InitializeTEAMPanel( ) // Add user data MSYS_SetRegionUserData( &gTEAM_SecondHandInv[ cnt ], 0, cnt ); + } @@ -3784,6 +3793,7 @@ void RenderTEAMPanel( BOOLEAN fDirty ) SOLDIERTYPE *pSoldier; static INT16 pStr[ 200 ], pMoraleStr[ 20 ]; + // WANNE 2 if ( fDirty == DIRTYLEVEL2 ) { MarkAButtonDirty( iTEAMPanelButtons[ TEAM_DONE_BUTTON ] ); @@ -3792,12 +3802,10 @@ void RenderTEAMPanel( BOOLEAN fDirty ) // Blit video surface - //if(gbPixelDepth==16) - //{ - BltVideoObjectFromIndex( guiSAVEBUFFER, guiTEAMPanel, 0, INTERFACE_START_X, INTERFACE_START_Y, VO_BLT_SRCTRANSPARENCY, NULL ); - //} - - RestoreExternBackgroundRect( INTERFACE_START_X, INTERFACE_START_Y, SCREEN_WIDTH - INTERFACE_START_X , INTERFACE_HEIGHT ); + BltVideoObjectFromIndex( guiSAVEBUFFER, guiTEAMPanel, 0, INTERFACE_START_X, INTERFACE_START_Y, VO_BLT_SRCTRANSPARENCY, NULL ); + RestoreExternBackgroundRect( INTERFACE_START_X, INTERFACE_START_Y, SCREEN_WIDTH - INTERFACE_START_X , INTERFACE_HEIGHT ); + + // WANNE 2 // LOOP THROUGH ALL MERCS ON TEAM PANEL for ( cnt = 0, posIndex = 0; cnt < NUM_TEAM_SLOTS; cnt++, posIndex+= 2 ) { @@ -4039,10 +4047,10 @@ void RenderTEAMPanel( BOOLEAN fDirty ) } } - } + UpdateTEAMPanel( ); - + if( fRenderRadarScreen == TRUE ) { // Render clock diff --git a/Tactical/Inventory Choosing.cpp b/Tactical/Inventory Choosing.cpp index 042c4ab7..8e7c20ed 100644 --- a/Tactical/Inventory Choosing.cpp +++ b/Tactical/Inventory Choosing.cpp @@ -253,7 +253,7 @@ void GenerateRandomEquipment( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass, INT8 { case SOLDIER_CLASS_NONE: // ammo is here only so that civilians with pre-assigned ammo will get some clips for it! - bAmmoClips = (INT8)(1 + Random( 2 )); + bAmmoClips = (INT8)(2 + Random( 2 )); // civilians get nothing, anyone who should get something should be preassigned by Linda break; @@ -274,7 +274,7 @@ void GenerateRandomEquipment( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass, INT8 if( Random( 2 ) ) bKnifeClass = bRating; - bAmmoClips = (INT8)(2 + Random( 2 )); + bAmmoClips = (INT8)(3 + Random( 2 )); if( bRating >= GOOD_ADMINISTRATOR_EQUIPMENT_RATING ) { @@ -316,7 +316,7 @@ void GenerateRandomEquipment( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass, INT8 bAttachClass = bRating; } - bAmmoClips = (INT8)(2 + Random( 2 )); + bAmmoClips = (INT8)(3 + Random( 2 )); if( bRating >= AVERAGE_ARMY_EQUIPMENT_RATING ) { @@ -429,7 +429,7 @@ void GenerateRandomEquipment( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass, INT8 } bAmmoClips = (INT8)(3 + Random( 2 )); - bGrenades = (INT8)(1 + Random( 3 )); + bGrenades = (INT8)(3 + Random( 3 )); if( ( bRating >= AVERAGE_ELITE_EQUIPMENT_RATING ) && ( Random( 100 ) < 75 ) ) { diff --git a/Tactical/Keys.cpp b/Tactical/Keys.cpp index bc2722c7..4c4dbc95 100644 --- a/Tactical/Keys.cpp +++ b/Tactical/Keys.cpp @@ -1309,7 +1309,7 @@ BOOLEAN AllMercsLookForDoor( INT16 sGridNo, BOOLEAN fUpdateValue ) if ( pSoldier->bLife >= OKLIFE && pSoldier->sGridNo != NOWHERE && pSoldier->bActive && pSoldier->bInSector ) { // is he close enough to see that gridno if he turns his head? - sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, 0 ); + sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, 0, pSoldier ); if (PythSpacesAway( pSoldier->sGridNo, sGridNo ) <= sDistVisible ) { @@ -1330,7 +1330,7 @@ BOOLEAN AllMercsLookForDoor( INT16 sGridNo, BOOLEAN fUpdateValue ) for ( cnt2 = 0; cnt2 < 8; cnt2++ ) { usNewGridNo = NewGridNo( sGridNo, DirectionInc( bDirs[ cnt2 ] ) ); - sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, usNewGridNo, 0 ); + sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, usNewGridNo, 0, pSoldier ); if (PythSpacesAway( pSoldier->sGridNo, usNewGridNo ) <= sDistVisible ) { @@ -1378,7 +1378,7 @@ BOOLEAN MercLooksForDoors( SOLDIERTYPE *pSoldier, BOOLEAN fUpdateValue ) sGridNo = pDoorStatus->sGridNo; // is he close enough to see that gridno if he turns his head? - sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, 0 ); + sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, 0, pSoldier ); if ( PythSpacesAway( pSoldier->sGridNo, sGridNo ) <= sDistVisible ) { diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index 32205242..47b3a569 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -7123,6 +7123,8 @@ BOOLEAN ProcessImplicationsOfPCAttack( SOLDIERTYPE * pSoldier, SOLDIERTYPE ** pp if ( pTarget->ubProfile == NO_PROFILE || !(gMercProfiles[ pTarget->ubProfile ].ubMiscFlags3 & PROFILE_MISC_FLAG3_TOWN_DOESNT_CARE_ABOUT_DEATH) ) { + //Kaiden: Added to keep Militia from going Hostile if you attack a Crow or Cow with an explosive. + if ( (pTarget->ubBodyType != CROW) && (pTarget->ubBodyType != COW) ) // militia, if any, turn hostile MilitiaChangesSides(); } diff --git a/Tactical/Rotting Corpses.cpp b/Tactical/Rotting Corpses.cpp index e29d38ce..f75cf099 100644 --- a/Tactical/Rotting Corpses.cpp +++ b/Tactical/Rotting Corpses.cpp @@ -1210,7 +1210,7 @@ void AllMercsOnTeamLookForCorpse( ROTTING_CORPSE *pCorpse, INT8 bTeam ) if ( pSoldier->bLife >= OKLIFE && pSoldier->sGridNo != NOWHERE && pSoldier->bActive && pSoldier->bInSector ) { // is he close enough to see that gridno if he turns his head? - sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, pCorpse->def.bLevel ); + sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, pCorpse->def.bLevel, pSoldier ); if (PythSpacesAway( pSoldier->sGridNo, sGridNo ) <= sDistVisible ) { @@ -1274,7 +1274,7 @@ void MercLooksForCorpses( SOLDIERTYPE *pSoldier ) sGridNo = pCorpse->def.sGridNo; // is he close enough to see that gridno if he turns his head? - sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, pCorpse->def.bLevel ); + sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, pCorpse->def.bLevel, pSoldier ); if (PythSpacesAway( pSoldier->sGridNo, sGridNo ) <= sDistVisible ) { diff --git a/Tactical/ShopKeeper Interface.cpp b/Tactical/ShopKeeper Interface.cpp index 26357208..d758eebe 100644 --- a/Tactical/ShopKeeper Interface.cpp +++ b/Tactical/ShopKeeper Interface.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #else @@ -79,6 +80,13 @@ SKIRGBCOLOR SkiGlowColorsA[]={ // /////////////////////////////////////////// +// WANNE 2 +#define SKI_INTERFACE_WIDTH 536 +#define SKI_INTERFACE_HEIGHT 340 + +#define SCREEN_X_OFFSET (((SCREEN_WIDTH - SKI_INTERFACE_WIDTH) / 2)) +#define SCREEN_Y_OFFSET ((((SCREEN_HEIGHT - INV_INTERFACE_HEIGHT) - (SKI_INTERFACE_HEIGHT)) / 2)) + #define SKI_BUTTON_FONT MILITARYFONT1//FONT14ARIAL #define SKI_BUTTON_COLOR 73 @@ -96,50 +104,50 @@ SKIRGBCOLOR SkiGlowColorsA[]={ #define SKIT_NUMBER_FONT BLOCKFONT2 -#define SKI_MAIN_BACKGROUND_X 0 -#define SKI_MAIN_BACKGROUND_Y 0 +#define SKI_MAIN_BACKGROUND_X SCREEN_X_OFFSET +#define SKI_MAIN_BACKGROUND_Y SCREEN_Y_OFFSET -#define SKI_FACE_X 13 -#define SKI_FACE_Y 13 +#define SKI_FACE_X (SCREEN_X_OFFSET + 13) +#define SKI_FACE_Y (SCREEN_Y_OFFSET + 13) #define SKI_FACE_WIDTH 90 #define SKI_FACE_HEIGHT 100 -#define SKI_PAGE_UP_ARROWS_X 121 -#define SKI_PAGE_UP_ARROWS_Y 35 +#define SKI_PAGE_UP_ARROWS_X (SCREEN_X_OFFSET + 121) +#define SKI_PAGE_UP_ARROWS_Y (SCREEN_Y_OFFSET + 35) #define SKI_PAGE_DOWN_ARROWS_X SKI_PAGE_UP_ARROWS_X -#define SKI_PAGE_DOWN_ARROWS_Y 102 +#define SKI_PAGE_DOWN_ARROWS_Y (SCREEN_Y_OFFSET + 102) //Evaluate: //#define SKI_EVALUATE_BUTTON_X 15 //#define SKI_EVALUATE_BUTTON_Y 233 -#define SKI_TRANSACTION_BUTTON_X 147//214 -#define SKI_TRANSACTION_BUTTON_Y 233//SKI_EVALUATE_BUTTON_Y +#define SKI_TRANSACTION_BUTTON_X (SCREEN_X_OFFSET + 147)//214 +#define SKI_TRANSACTION_BUTTON_Y (SCREEN_Y_OFFSET +233)//SKI_EVALUATE_BUTTON_Y -#define SKI_DONE_BUTTON_X 292//414 -#define SKI_DONE_BUTTON_Y 233//SKI_EVALUATE_BUTTON_Y +#define SKI_DONE_BUTTON_X (SCREEN_X_OFFSET + 292)//414 +#define SKI_DONE_BUTTON_Y (SCREEN_Y_OFFSET + 233)//SKI_EVALUATE_BUTTON_Y -#define SKI_MAIN_TITLE_X 112 -#define SKI_MAIN_TITLE_Y 12 +#define SKI_MAIN_TITLE_X (SCREEN_X_OFFSET + 112) +#define SKI_MAIN_TITLE_Y (SCREEN_Y_OFFSET + 12) #define SKI_MAIN_TITLE_WIDTH 420 -#define SKI_TOTAL_COST_X 9 -#define SKI_TOTAL_COST_Y 162//159 +#define SKI_TOTAL_COST_X (SCREEN_X_OFFSET + 9) +#define SKI_TOTAL_COST_Y (SCREEN_Y_OFFSET + 162)//159 #define SKI_TOTAL_COST_WIDTH 73 #define SKI_TOTAL_VALUE_X SKI_TOTAL_COST_X -#define SKI_TOTAL_VALUE_Y 291//268 +#define SKI_TOTAL_VALUE_Y (SCREEN_Y_OFFSET + 291)//268 #define SKI_TOTAL_VALUE_WIDTH SKI_TOTAL_COST_WIDTH -#define SKI_PLAYERS_CURRENT_BALANCE_X SKI_TOTAL_COST_X -#define SKI_PLAYERS_CURRENT_BALANCE_Y 235 -#define SKI_PLAYERS_CURRENT_BALANCE_WIDTH SKI_TOTAL_COST_WIDTH -#define SKI_PLAYERS_CURRENT_BALANCE_OFFSET_TO_VALUE 265 +#define SKI_PLAYERS_CURRENT_BALANCE_X SKI_TOTAL_COST_X +#define SKI_PLAYERS_CURRENT_BALANCE_Y (SCREEN_Y_OFFSET + 235) +#define SKI_PLAYERS_CURRENT_BALANCE_WIDTH SKI_TOTAL_COST_WIDTH +#define SKI_PLAYERS_CURRENT_BALANCE_OFFSET_TO_VALUE SCREEN_Y_OFFSET + 265 -#define SKI_PAGE_X 112 -#define SKI_PAGE_Y 70 +#define SKI_PAGE_X (SCREEN_X_OFFSET + 112) +#define SKI_PAGE_Y (SCREEN_Y_OFFSET + 70) #define SKI_PAGE_WIDTH 45 #define SKI_PAGE_HEIGHT 27 @@ -166,49 +174,48 @@ SKIRGBCOLOR SkiGlowColorsA[]={ #define SKI_GLOW_DELAY 70 //Start Locations for the inventory boxes -#define SKI_ARMS_DEALERS_INV_START_X 165 -#define SKI_ARMS_DEALERS_INV_START_Y 30 +#define SKI_ARMS_DEALERS_INV_START_X (SCREEN_X_OFFSET + 165) +#define SKI_ARMS_DEALERS_INV_START_Y (SCREEN_Y_OFFSET + 30) -#define SKI_ARMS_DEALERS_TRADING_INV_X 91 -#define SKI_ARMS_DEALERS_TRADING_INV_Y 151 +#define SKI_ARMS_DEALERS_TRADING_INV_X (SCREEN_X_OFFSET + 91) +#define SKI_ARMS_DEALERS_TRADING_INV_Y (SCREEN_Y_OFFSET + 151) #define SKI_ARMS_DEALERS_TRADING_INV_WIDTH 436 #define SKI_ARMS_DEALERS_TRADING_INV_HEIGHT 67 - -#define SKI_PLAYERS_TRADING_INV_X 91 -#define SKI_PLAYERS_TRADING_INV_Y 266 +#define SKI_PLAYERS_TRADING_INV_X (SCREEN_X_OFFSET + 91) +#define SKI_PLAYERS_TRADING_INV_Y (SCREEN_Y_OFFSET + 266) #define SKI_PLAYERS_TRADING_INV_HEIGHT 70 #define SKI_PLAYERS_TRADING_INV_WIDTH 440 -#define SKI_ARMS_DEALER_TOTAL_COST_X 16 -#define SKI_ARMS_DEALER_TOTAL_COST_Y 194//191 +#define SKI_ARMS_DEALER_TOTAL_COST_X (SCREEN_X_OFFSET + 16) +#define SKI_ARMS_DEALER_TOTAL_COST_Y (SCREEN_Y_OFFSET + 194)//191 #define SKI_ARMS_DEALER_TOTAL_COST_WIDTH 59 #define SKI_ARMS_DEALER_TOTAL_COST_HEIGHT 20 -#define SKI_PLAYERS_TOTAL_VALUE_X 16 -#define SKI_PLAYERS_TOTAL_VALUE_Y 310//308 +#define SKI_PLAYERS_TOTAL_VALUE_X (SCREEN_X_OFFSET + 16) +#define SKI_PLAYERS_TOTAL_VALUE_Y (SCREEN_Y_OFFSET + 310)//308 #define SKI_PLAYERS_TOTAL_VALUE_WIDTH 59 #define SKI_PLAYERS_TOTAL_VALUE_HEIGHT 20 -#define SKI_TACTICAL_BACKGROUND_START_X 536 +#define SKI_TACTICAL_BACKGROUND_START_X (SCREEN_X_OFFSET + SKI_INTERFACE_WIDTH) + #define SKI_TACTICAL_BACKGROUND_START_Y 0 + #define SKI_DROP_ITEM_TO_GROUND_START_X SKI_TACTICAL_BACKGROUND_START_X -#define SKI_DROP_ITEM_TO_GROUND_START_Y 262 -#define SKI_DROP_ITEM_TO_GROUND_TEXT_START_Y 262 +#define SKI_DROP_ITEM_TO_GROUND_START_Y (SCREEN_Y_OFFSET + 262) +#define SKI_DROP_ITEM_TO_GROUND_TEXT_START_Y (SCREEN_Y_OFFSET + 262) -#define SKI_TACTICAL_BACKGROUND_START_WIDTH 640 - SKI_TACTICAL_BACKGROUND_START_X -#define SKI_TACTICAL_BACKGROUND_START_HEIGHT 340 +#define SKI_TACTICAL_BACKGROUND_START_WIDTH (SCREEN_WIDTH - SKI_TACTICAL_BACKGROUND_START_X) -#define SKI_ITEM_MOVEMENT_AREA_X 85 -#define SKI_ITEM_MOVEMENT_AREA_Y 263 -#define SKI_ITEM_MOVEMENT_AREA_WIDTH (640 - SKI_ITEM_MOVEMENT_AREA_X) -//#define SKI_ITEM_MOVEMENT_AREA_WIDTH 448 -#define SKI_ITEM_MOVEMENT_AREA_HEIGHT 215//72 +#define SKI_TACTICAL_BACKGROUND_START_HEIGHT (SCREEN_HEIGHT - INV_INTERFACE_HEIGHT) -#define SKI_DEALER_OFFER_AREA_Y 148 -//#define SKI_DEALER_OFFER_AREA_Y 148 +#define SKI_ITEM_MOVEMENT_AREA_X (SCREEN_X_OFFSET + 85) +#define SKI_ITEM_MOVEMENT_AREA_Y (SCREEN_Y_OFFSET + 263) +#define SKI_ITEM_MOVEMENT_AREA_WIDTH (SCREEN_WIDTH - SKI_ITEM_MOVEMENT_AREA_X) +#define SKI_ITEM_MOVEMENT_AREA_HEIGHT (SCREEN_Y_OFFSET + 215)//72 +#define SKI_DEALER_OFFER_AREA_Y (SCREEN_Y_OFFSET + 148) #define SKI_ITEM_NUMBER_TEXT_OFFSET_X 50 #define SKI_ITEM_NUMBER_TEXT_OFFSET_Y 15 @@ -216,7 +223,7 @@ SKIRGBCOLOR SkiGlowColorsA[]={ #define SKI_SUBTITLE_TEXT_SIZE 512 -#define SKI_POSITION_SUBTITLES_Y 140//100 +#define SKI_POSITION_SUBTITLES_Y (SCREEN_Y_OFFSET + INV_INTERFACE_HEIGHT)//100 #define SKI_SMALL_FACE_WIDTH 16 #define SKI_SMALL_FACE_HEIGHT 14 @@ -227,8 +234,8 @@ SKIRGBCOLOR SkiGlowColorsA[]={ #define SKI_ATTACHMENT_SYMBOL_Y_OFFSET 14 -#define SKI_ATM_PANEL_X 87 -#define SKI_ATM_PANEL_Y 342 +#define SKI_ATM_PANEL_X (SCREEN_X_OFFSET + 87) +#define SKI_ATM_PANEL_Y (SCREEN_Y_OFFSET + SKI_INTERFACE_HEIGHT) #define SKI_ATM_PANEL_WIDTH 127 #define SKI_ATM_PANEL_HEIGHT 135 @@ -236,7 +243,7 @@ SKIRGBCOLOR SkiGlowColorsA[]={ #define SKI_ATM_BUTTON_Y SKI_ATM_PANEL_Y + 64 #define SKI_ATM_BUTTON_HEIGHT 15 #define SKI_ATM_NUM_BUTTON_WIDTH 15 -#define SKI_ATM_SIDE_MENU_PANEL_START_X 48 +#define SKI_ATM_SIDE_MENU_PANEL_START_X (SCREEN_X_OFFSET + 48) #define SKI_TRANSFER_STRING_X SKI_ATM_PANEL_X + 22 #define SKI_TRANSFER_STRING_Y SKI_ATM_PANEL_Y + 50 @@ -705,7 +712,8 @@ UINT32 ShopKeeperScreenHandle() } gubSkiDirtyLevel = SKI_DIRTY_LEVEL2; gfRenderScreenOnNextLoop = TRUE; - InvalidateRegion( 0, 0, 640, 480 ); + + InvalidateRegion( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); } if( gfRenderScreenOnNextLoop ) @@ -810,7 +818,6 @@ BOOLEAN EnterShopKeeperInterface() // make sure current merc is close enough and eligible to talk to the shopkeeper. AssertMsg( CanMercInteractWithSelectedShopkeeper( MercPtrs[ gusSelectedSoldier ] ), "Selected merc can't interact with shopkeeper. Send save AM-1"); - // Create a video surface to blt corner of the tactical screen that still shines through vs_desc.fCreateFlags = VSURFACE_CREATE_DEFAULT | VSURFACE_SYSTEM_MEM_USAGE; vs_desc.usWidth = SKI_TACTICAL_BACKGROUND_START_WIDTH; @@ -829,6 +836,9 @@ BOOLEAN EnterShopKeeperInterface() //Clear out all the save background rects EmptyBackgroundRects( ); + // WANNE 2 + ShadowVideoSurfaceRect( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT - INV_INTERFACE_HEIGHT ); + if( gfExitSKIDueToMessageBox ) { gubSkiDirtyLevel = SKI_DIRTY_LEVEL2; @@ -973,7 +983,7 @@ ATM: //Blanket the entire screen - MSYS_DefineRegion( &gSKI_EntireScreenMouseRegions, 0, 0, 639, 339, MSYS_PRIORITY_HIGH-2, + MSYS_DefineRegion( &gSKI_EntireScreenMouseRegions, 0, 0, (SCREEN_WIDTH - 1), (SCREEN_HEIGHT - INV_INTERFACE_HEIGHT), MSYS_PRIORITY_HIGH-2, CURSOR_NORMAL, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK); MSYS_AddRegion( &gSKI_EntireScreenMouseRegions ); @@ -1025,6 +1035,8 @@ ATM: //Setup the currently selected arms dealer InitializeShopKeeper( TRUE ); + + //Set the flag indicating that we are in the shop keeper interface guiTacticalInterfaceFlags |= INTERFACE_SHOPKEEP_INTERFACE; @@ -1107,7 +1119,7 @@ ATM: //Region to allow the user to drop items to the ground - MSYS_DefineRegion( &gArmsDealersDropItemToGroundMouseRegions, SKI_DROP_ITEM_TO_GROUND_START_X, SKI_DROP_ITEM_TO_GROUND_START_Y, 639, 339, MSYS_PRIORITY_HIGH, + MSYS_DefineRegion( &gArmsDealersDropItemToGroundMouseRegions, SKI_DROP_ITEM_TO_GROUND_START_X, SKI_DROP_ITEM_TO_GROUND_START_Y, SCREEN_WIDTH - 1, SCREEN_HEIGHT - INV_INTERFACE_HEIGHT, MSYS_PRIORITY_HIGH, CURSOR_NORMAL, SelectArmsDealersDropItemToGroundMovementRegionCallBack, SelectArmsDealersDropItemToGroundRegionCallBack ); // CURSOR_NORMAL, MSYS_NO_CALLBACK, SelectArmsDealersDropItemToGroundRegionCallBack ); MSYS_AddRegion( &gArmsDealersDropItemToGroundMouseRegions ); @@ -1439,7 +1451,7 @@ BOOLEAN RenderShopKeeperInterface() SrcRect.iRight = SKI_TACTICAL_BACKGROUND_START_X + SKI_TACTICAL_BACKGROUND_START_WIDTH; SrcRect.iBottom = SKI_TACTICAL_BACKGROUND_START_Y + SKI_TACTICAL_BACKGROUND_START_HEIGHT; - BltVSurfaceUsingDD( hDestVSurface, hSrcVSurface, VO_BLT_SRCTRANSPARENCY, 0, 0, (RECT*)&SrcRect ); + BltVSurfaceUsingDD( hDestVSurface, hSrcVSurface, VO_BLT_SRCTRANSPARENCY, SKI_TACTICAL_BACKGROUND_START_X, SKI_TACTICAL_BACKGROUND_START_Y, (RECT*)&SrcRect ); gfRenderScreenOnNextLoop = FALSE; } @@ -1466,7 +1478,7 @@ BOOLEAN RenderShopKeeperInterface() //Restore the tactical background that is visble behind the SKI panel RestoreTacticalBackGround(); - InvalidateRegion( 0, 0, 640, 480 ); + InvalidateRegion( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); return( TRUE ); } @@ -1476,23 +1488,21 @@ void RestoreTacticalBackGround() HVSURFACE hDestVSurface, hSrcVSurface; SGPRect SrcRect; - //Restore the background before blitting the text back on -// RestoreExternBackgroundRect( SKI_TACTICAL_BACKGROUND_START_X, SKI_TACTICAL_BACKGROUND_START_Y, SKI_TACTICAL_BACKGROUND_START_WIDTH, SKI_TACTICAL_BACKGROUND_START_HEIGHT ); - -// BlitBufferToBuffer( guiCornerWhereTacticalIsStillSeenImage, guiRENDERBUFFER, SKI_TACTICAL_BACKGROUND_START_X, SKI_TACTICAL_BACKGROUND_START_Y, SKI_TACTICAL_BACKGROUND_START_WIDTH, SKI_TACTICAL_BACKGROUND_START_HEIGHT ); - GetVideoSurface( &hDestVSurface, guiRENDERBUFFER ); GetVideoSurface( &hSrcVSurface, guiCornerWhereTacticalIsStillSeenImage ); - SrcRect.iLeft = 0; - SrcRect.iTop = 0; - SrcRect.iRight = SKI_TACTICAL_BACKGROUND_START_WIDTH; - SrcRect.iBottom = SKI_TACTICAL_BACKGROUND_START_HEIGHT; - + // WANNE 2 + // Top + SrcRect.iLeft = SKI_TACTICAL_BACKGROUND_START_X; //0; + SrcRect.iTop = SKI_TACTICAL_BACKGROUND_START_Y; //0; + SrcRect.iRight = SKI_TACTICAL_BACKGROUND_START_WIDTH; //SKI_TACTICAL_BACKGROUND_START_WIDTH; + SrcRect.iBottom = SKI_TACTICAL_BACKGROUND_START_HEIGHT; //SKI_TACTICAL_BACKGROUND_START_HEIGHT; + BltVSurfaceUsingDD( hDestVSurface, hSrcVSurface, VO_BLT_SRCTRANSPARENCY, SKI_TACTICAL_BACKGROUND_START_X, SKI_TACTICAL_BACKGROUND_START_Y, (RECT*)&SrcRect ); - InvalidateRegion( 0, 0, 640, 480 ); + // WANNE 2 + //InvalidateRegion( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); } @@ -1571,7 +1581,7 @@ void GetShopKeeperInterfaceUserInput() gubSkiDirtyLevel = SKI_DIRTY_LEVEL2; break; case 'i': - InvalidateRegion( 0, 0, 640, 480 ); + InvalidateRegion( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); break; case 'd': @@ -1599,7 +1609,7 @@ void DisplayAllDealersCash() for( bArmsDealer=0; bArmsDealer 640 ) - sPosX = sPosX - ( ( sPosX + 358 ) - 640 ) - 5; + if( ( sPosX + 358 ) > SCREEN_WIDTH ) + sPosX = sPosX - ( ( sPosX + 358 ) - SCREEN_WIDTH ) - 5; //if it is starting to far to the left - else if( sPosX < 0 ) - sPosX = 0; + else if( sPosX < (0 + SCREEN_X_OFFSET) ) + sPosX = 0 + SCREEN_X_OFFSET; //if the box will appear over the mercs face, move the box over so it doesn't obstruct the face if( sPosY < SKI_FACE_Y + SKI_FACE_HEIGHT + 20 ) - if( sPosX < 160 ) - sPosX = 160; + if( sPosX < (SCREEN_X_OFFSET + 160) ) + sPosX = SCREEN_X_OFFSET + 160; } break; @@ -6340,22 +6354,22 @@ void InitShopKeeperItemDescBox( OBJECTTYPE *pObject, UINT8 ubPocket, UINT8 ubFro sPosY = SKI_ARMS_DEALERS_TRADING_INV_Y + ( ( SKI_INV_OFFSET_Y * ubPocket / ( SKI_NUM_TRADING_INV_SLOTS/2) ) + 1 ) - ( 128 / 2 ) + SKI_INV_SLOT_HEIGHT / 2; //if the start position + the height of the box is off the screen, reposition - if( sPosY < 0 ) - sPosY = 0; + if( sPosY < (SCREEN_Y_OFFSET + 0) ) + sPosY = 0 + SCREEN_Y_OFFSET; //if the start position + the width of the box is off the screen, reposition - if( ( sPosX + 358 ) > 640 ) - sPosX = sPosX - ( ( sPosX + 358 ) - 640 ) - 5; + if( ( sPosX + 358 ) > SCREEN_WIDTH ) + sPosX = sPosX - ( ( sPosX + 358 ) - SCREEN_WIDTH ) - 5; //if it is starting to far to the left - else if( sPosX < 0 ) - sPosX = 10; + else if( sPosX < (0 + SCREEN_X_OFFSET) ) + sPosX = 10 + SCREEN_X_OFFSET; //if the box will appear over the mercs face, move the box over so it doesn't obstruct the face if( sPosY < SKI_FACE_Y + SKI_FACE_HEIGHT + 20 ) - if( sPosX < 160 ) - sPosY = 140; + if( sPosX < (160 + SCREEN_X_OFFSET) ) + sPosY = SCREEN_Y_OFFSET + INV_INTERFACE_HEIGHT; } break; @@ -6377,17 +6391,20 @@ void StartSKIDescriptionBox( void ) { INT32 iCnt; - //shadow the entire screen // ShadowVideoSurfaceRect( FRAME_BUFFER, 0, 0, 640, 480 ); //if the current merc is too far away, dont shade the SM panel because it is already shaded + + // WANNE 2: Do not shade the background if( gfSMDisableForItems ) - DrawHatchOnInventory( FRAME_BUFFER, 0, 0, 640, 338 ); + DrawHatchOnInventory( FRAME_BUFFER, SCREEN_X_OFFSET, SCREEN_Y_OFFSET, SKI_INTERFACE_WIDTH, SKI_INTERFACE_HEIGHT ); else - DrawHatchOnInventory( FRAME_BUFFER, 0, 0, 640, 480 ); + { + DrawHatchOnInventory( FRAME_BUFFER, SCREEN_X_OFFSET, SCREEN_Y_OFFSET, SKI_INTERFACE_WIDTH, SKI_INTERFACE_HEIGHT ); + } - InvalidateRegion( 0, 0, 640, 480 ); + InvalidateRegion( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); // disable almost everything! @@ -7044,7 +7061,7 @@ BOOLEAN CanMercInteractWithSelectedShopkeeper( SOLDIERTYPE *pSoldier ) bDestLevel = pShopkeeper->bLevel; // is he close enough to see that gridno if he turns his head? - sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sDestGridNo, bDestLevel ); + sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sDestGridNo, bDestLevel, pSoldier ); // If he has LOS... if ( SoldierTo3DLocationLineOfSightTest( pSoldier, sDestGridNo, bDestLevel, 3, (UINT8) sDistVisible, TRUE ) ) @@ -7462,6 +7479,8 @@ void DelayRepairsInProgressBy( UINT32 uiMinutesDelayed ) //Mouse Call back for the Arms delaers face void SelectArmsDealersDropItemToGroundRegionCallBack(MOUSE_REGION * pRegion, INT32 iReason ) { + // WANNE 2: not needed to drop the item to the ground -> on the right side of the shopkeeper screen! + /* if (iReason & MSYS_CALLBACK_REASON_INIT) { } @@ -7482,6 +7501,7 @@ void SelectArmsDealersDropItemToGroundRegionCallBack(MOUSE_REGION * pRegion, INT //if we don't have an item, pick one up if( gMoveingItem.sItemIndex != 0 ) { + //add the item to the ground ShopkeeperAddItemToPool( pDropSoldier->sGridNo, &gMoveingItem.ItemObject, VISIBLE, pDropSoldier->bLevel, 0, 0 ); @@ -7492,6 +7512,7 @@ void SelectArmsDealersDropItemToGroundRegionCallBack(MOUSE_REGION * pRegion, INT gubSkiDirtyLevel = SKI_DIRTY_LEVEL2; } } + */ } void SelectArmsDealersDropItemToGroundMovementRegionCallBack(MOUSE_REGION * pRegion, INT32 iReason ) @@ -7533,10 +7554,11 @@ void DisplayTheSkiDropItemToGroundString() UINT16 usHeight; //get the height of the displayed text - usHeight = DisplayWrappedString( SKI_DROP_ITEM_TO_GROUND_START_X, SKI_DROP_ITEM_TO_GROUND_TEXT_START_Y, (UINT16)(640-SKI_DROP_ITEM_TO_GROUND_START_X), 2, SKI_LABEL_FONT, SKI_TITLE_COLOR, SKI_Text[ SKI_TEXT_DROP_ITEM_TO_GROUND ], FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED | DONT_DISPLAY_TEXT ); + usHeight = DisplayWrappedString( SKI_DROP_ITEM_TO_GROUND_START_X, SKI_DROP_ITEM_TO_GROUND_TEXT_START_Y, (UINT16)(SCREEN_WIDTH-SKI_DROP_ITEM_TO_GROUND_START_X), 2, SKI_LABEL_FONT, SKI_TITLE_COLOR, SKI_Text[ SKI_TEXT_DROP_ITEM_TO_GROUND ], FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED | DONT_DISPLAY_TEXT ); + // WANNE 2 - not needed to show the string //display the 'drop item to ground' text - DisplayWrappedString( SKI_DROP_ITEM_TO_GROUND_START_X, (UINT16)(SKI_DROP_ITEM_TO_GROUND_TEXT_START_Y-usHeight), (UINT16)(640-SKI_DROP_ITEM_TO_GROUND_START_X), 2, SKI_LABEL_FONT, SKI_TITLE_COLOR, SKI_Text[ SKI_TEXT_DROP_ITEM_TO_GROUND ], FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED | INVALIDATE_TEXT ); + //DisplayWrappedString( SKI_DROP_ITEM_TO_GROUND_START_X, (UINT16)(SKI_DROP_ITEM_TO_GROUND_TEXT_START_Y-usHeight), (UINT16)(SCREEN_WIDTH-SKI_DROP_ITEM_TO_GROUND_START_X), 2, SKI_LABEL_FONT, SKI_TITLE_COLOR, SKI_Text[ SKI_TEXT_DROP_ITEM_TO_GROUND ], FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED | INVALIDATE_TEXT ); } diff --git a/Tactical/SkillCheck.cpp b/Tactical/SkillCheck.cpp index 5d57e2ce..999a38e1 100644 --- a/Tactical/SkillCheck.cpp +++ b/Tactical/SkillCheck.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #else @@ -23,8 +24,17 @@ INT8 EffectiveStrength( SOLDIERTYPE * pSoldier ) // 1/2 full strength // plus 1/2 strength scaled according to how hurt we are bBandaged = pSoldier->bLifeMax - pSoldier->bLife - pSoldier->bBleeding; - iEffStrength = pSoldier->bStrength / 2; - iEffStrength += (pSoldier->bStrength / 2) * (pSoldier->bLife + bBandaged / 2) / (pSoldier->bLifeMax); + + // WANNE 2 + if (pSoldier->bStrength > 0) + { + iEffStrength = pSoldier->bStrength / 2; + iEffStrength += (pSoldier->bStrength / 2) * (pSoldier->bLife + bBandaged / 2) / (pSoldier->bLifeMax); + } + else + { + iEffStrength = 0; + } // ATE: Make sure at least 2... iEffStrength = __max( iEffStrength, 2 ); diff --git a/Tactical/Soldier Ani.cpp b/Tactical/Soldier Ani.cpp index 5fd3038b..96cc826a 100644 --- a/Tactical/Soldier Ani.cpp +++ b/Tactical/Soldier Ani.cpp @@ -2909,7 +2909,7 @@ void SayBuddyWitnessedQuoteFromKill( SOLDIERTYPE *pKillerSoldier, INT16 sGridNo, // TO LOS check to killed // Can we see location of killer? - sDistVisible = DistanceVisible( pTeamSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, pKillerSoldier->sGridNo, pKillerSoldier->bLevel ); + sDistVisible = DistanceVisible( pTeamSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, pKillerSoldier->sGridNo, pKillerSoldier->bLevel, pKillerSoldier ); if ( SoldierTo3DLocationLineOfSightTest( pTeamSoldier, pKillerSoldier->sGridNo, pKillerSoldier->bLevel, (UINT8)3, (UINT8) sDistVisible, TRUE ) == 0 ) { continue; @@ -2917,7 +2917,7 @@ void SayBuddyWitnessedQuoteFromKill( SOLDIERTYPE *pKillerSoldier, INT16 sGridNo, // Can we see location of killed? - sDistVisible = DistanceVisible( pTeamSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel ); + sDistVisible = DistanceVisible( pTeamSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel, pTeamSoldier ); if ( SoldierTo3DLocationLineOfSightTest( pTeamSoldier, sGridNo, bLevel, (UINT8)3, (UINT8) sDistVisible, TRUE ) == 0 ) { continue; @@ -2976,7 +2976,7 @@ void HandleKilledQuote( SOLDIERTYPE *pKilledSoldier, SOLDIERTYPE *pKillerSoldier gfLastMercTalkedAboutKillingID = pKilledSoldier->ubID; // Can we see location? - sDistVisible = DistanceVisible( pKillerSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel ); + sDistVisible = DistanceVisible( pKillerSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel, pKillerSoldier ); fCanWeSeeLocation = ( SoldierTo3DLocationLineOfSightTest( pKillerSoldier, sGridNo, bLevel, (UINT8)3, (UINT8) sDistVisible, TRUE ) != 0 ); @@ -3039,7 +3039,7 @@ void HandleKilledQuote( SOLDIERTYPE *pKilledSoldier, SOLDIERTYPE *pKillerSoldier if ( OK_INSECTOR_MERC( pTeamSoldier ) && !( pTeamSoldier->uiStatusFlags & SOLDIER_GASSED ) && !AM_AN_EPC( pTeamSoldier ) ) { // Can we see location? - sDistVisible = DistanceVisible( pTeamSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel ); + sDistVisible = DistanceVisible( pTeamSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel, pTeamSoldier ); if ( SoldierTo3DLocationLineOfSightTest( pTeamSoldier, sGridNo, bLevel, 3, (UINT8) sDistVisible, TRUE ) ) { diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index d740fade..b744321f 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -574,8 +574,41 @@ INT8 CalcActionPoints(SOLDIERTYPE *pSold) } //Madd - if ( pSold->bTeam != CIV_TEAM && pSold->bTeam != gbPlayerNum && gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) - ubPoints += 5; // everything and everyone moves a little faster against you on insane... +// if ( pSold->bTeam != CIV_TEAM && pSold->bTeam != gbPlayerNum && gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) +// ubPoints += 5; // everything and everyone moves a little faster against you on insane... + + + //Kaiden: Took your idea a step further adding the bonus for each difficulty level + // and then externalized it. AND added it to the Dont max out points section below. + if ( pSold->bTeam != CIV_TEAM && pSold->bTeam != gbPlayerNum) + { + + switch( gGameOptions.ubDifficultyLevel ) + { + case DIF_LEVEL_EASY: + + ubPoints += gGameExternalOptions.iEasyAPBonus; + break; + + case DIF_LEVEL_MEDIUM: + + ubPoints += gGameExternalOptions.iExperiencedAPBonus; + break; + + case DIF_LEVEL_HARD: + + ubPoints += gGameExternalOptions.iExpertAPBonus; + break; + + case DIF_LEVEL_INSANE: + + ubPoints += gGameExternalOptions.iInsaneAPBonus; + break; + + default: + ubPoints +=0; + } + } // if we are in boxing mode, adjust APs... THIS MUST BE LAST! if ( gTacticalStatus.bBoxingState == BOXING || gTacticalStatus.bBoxingState == PRE_BOXING ) @@ -608,8 +641,43 @@ void CalcNewActionPoints( SOLDIERTYPE *pSoldier ) // Don't max out if we are drugged.... if ( !GetDrugEffect( pSoldier, DRUG_TYPE_ADRENALINE ) ) - { + { //Kaiden: If Enemy, they can max out, but their Max is NOW = MAX + diffAPBonus + // No sense in giving them a bonus if some of the points are wasted because we + // Didn't raise their cap by the same amount. + if ( pSoldier->bTeam != CIV_TEAM && pSoldier->bTeam != gbPlayerNum) + { + switch( gGameOptions.ubDifficultyLevel ) + { + case DIF_LEVEL_EASY: + + pSoldier->bActionPoints = __min( pSoldier->bActionPoints, (gubMaxActionPoints[ pSoldier->ubBodyType ] + gGameExternalOptions.iEasyAPBonus)); + break; + + case DIF_LEVEL_MEDIUM: + + pSoldier->bActionPoints = __min( pSoldier->bActionPoints, (gubMaxActionPoints[ pSoldier->ubBodyType ] + gGameExternalOptions.iExperiencedAPBonus)); + break; + + case DIF_LEVEL_HARD: + + pSoldier->bActionPoints = __min( pSoldier->bActionPoints, (gubMaxActionPoints[ pSoldier->ubBodyType ] + gGameExternalOptions.iExpertAPBonus)); + break; + + case DIF_LEVEL_INSANE: + + pSoldier->bActionPoints = __min( pSoldier->bActionPoints, (gubMaxActionPoints[ pSoldier->ubBodyType ] + gGameExternalOptions.iInsaneAPBonus)); + break; + + default: pSoldier->bActionPoints = __min( pSoldier->bActionPoints, gubMaxActionPoints[ pSoldier->ubBodyType ] ); + } + + } + else + { //Kaiden: Players just max out normally unless drugged + pSoldier->bActionPoints = __min( pSoldier->bActionPoints, gubMaxActionPoints[ pSoldier->ubBodyType ] ); + } + } pSoldier->bInitialActionPoints = pSoldier->bActionPoints; @@ -2665,7 +2733,7 @@ void SetSoldierGridNo( SOLDIERTYPE *pSoldier, INT16 sNewGridNo, BOOLEAN fForceRe // if we SEE this particular oppponent, and he DOESN'T see us... and he COULD see us... if ( (pSoldier->bOppList[ cnt ] == SEEN_CURRENTLY) && pEnemy->bOppList[ pSoldier->ubID ] != SEEN_CURRENTLY && - PythSpacesAway( pSoldier->sGridNo, pEnemy->sGridNo ) < DistanceVisible( pEnemy, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, pSoldier->sGridNo, pSoldier->bLevel ) ) + PythSpacesAway( pSoldier->sGridNo, pEnemy->sGridNo ) < DistanceVisible( pEnemy, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, pSoldier->sGridNo, pSoldier->bLevel, pSoldier ) ) { // AGILITY (5): Soldier snuck 1 square past unaware enemy StatChange( pSoldier, AGILAMT, 5, FALSE ); @@ -6120,11 +6188,22 @@ void MoveMercFacingDirection( SOLDIERTYPE *pSoldier, BOOLEAN fReverse, FLOAT dMo void BeginSoldierClimbUpRoof( SOLDIERTYPE *pSoldier ) { INT8 bNewDirection; + UINT8 ubWhoIsThere; + if ( FindHeigherLevel( pSoldier, pSoldier->sGridNo, pSoldier->bDirection, &bNewDirection ) && ( pSoldier->bLevel == 0 ) ) { if ( EnoughPoints( pSoldier, GetAPsToClimbRoof( pSoldier, FALSE ), 0, TRUE ) ) { + //Kaiden: Helps if we look where we are going before we try to climb on top of someone + ubWhoIsThere = WhoIsThere2( NewGridNo( (UINT16)pSoldier->sGridNo, (UINT16)DirectionInc(bNewDirection ) ), 1 ); + if ( ubWhoIsThere != NOBODY && ubWhoIsThere != pSoldier->ubID ) + { + return; + } + else + { + if (pSoldier->bTeam == gbPlayerNum) { // OK, SET INTERFACE FIRST @@ -6141,6 +6220,8 @@ void BeginSoldierClimbUpRoof( SOLDIERTYPE *pSoldier ) InternalGivingSoldierCancelServices( pSoldier, FALSE ); } + + } } } @@ -7329,17 +7410,31 @@ BOOLEAN CheckSoldierHitRoof( SOLDIERTYPE *pSoldier ) void BeginSoldierClimbDownRoof( SOLDIERTYPE *pSoldier ) { INT8 bNewDirection; + UINT8 ubWhoIsThere; + if ( FindLowerLevel( pSoldier, pSoldier->sGridNo, pSoldier->bDirection, &bNewDirection ) && ( pSoldier->bLevel > 0 ) ) { if ( EnoughPoints( pSoldier, GetAPsToClimbRoof( pSoldier, TRUE ), 0, TRUE ) ) { + //Kaiden: Helps if we look where we are going before we try to climb on top of someone + ubWhoIsThere = WhoIsThere2( NewGridNo( (UINT16)pSoldier->sGridNo, (UINT16)DirectionInc(bNewDirection ) ), 0 ); + if ( ubWhoIsThere != NOBODY && ubWhoIsThere != pSoldier->ubID ) + { + return; + } + else + { + if (pSoldier->bTeam == gbPlayerNum) { // OK, SET INTERFACE FIRST SetUIBusy( pSoldier->ubID ); } + + + pSoldier->sTempNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, (UINT16)DirectionInc(bNewDirection ) ); bNewDirection = gTwoCDirection[ bNewDirection ]; @@ -7352,8 +7447,46 @@ void BeginSoldierClimbDownRoof( SOLDIERTYPE *pSoldier ) } } + } } +/* +void BeginSoldierClimbDownRoof( SOLDIERTYPE *pSoldier ) +{ + INT8 bNewDirection; + UINT8 ubWhoIsThere; + + + if ( FindLowerLevel( pSoldier, pSoldier->sGridNo, pSoldier->bDirection, &bNewDirection ) && ( pSoldier->bLevel > 0 ) ) + { + if ( EnoughPoints( pSoldier, GetAPsToClimbRoof( pSoldier, TRUE ), 0, TRUE ) ) + { + if (pSoldier->bTeam == gbPlayerNum) + { + // OK, SET INTERFACE FIRST + SetUIBusy( pSoldier->ubID ); + } + + + + + pSoldier->sTempNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, (UINT16)DirectionInc(bNewDirection ) ); + + bNewDirection = gTwoCDirection[ bNewDirection ]; + + pSoldier->ubPendingDirection = bNewDirection; + EVENT_InitNewSoldierAnim( pSoldier, CLIMBDOWNROOF, 0 , FALSE ); + + InternalReceivingSoldierCancelServices( pSoldier, FALSE ); + InternalGivingSoldierCancelServices( pSoldier, FALSE ); + + } + } + +} +*/ + + void MoveMerc( SOLDIERTYPE *pSoldier, FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckRange ) { diff --git a/Tactical/Soldier Profile.h b/Tactical/Soldier Profile.h index b952afd8..b77b52be 100644 --- a/Tactical/Soldier Profile.h +++ b/Tactical/Soldier Profile.h @@ -53,7 +53,7 @@ enum NPCIDs PERKO, QUEEN, AUNTIE, - ENRICO, + GABBY, //ENRICO, CARMEN, JOE, STEVE, @@ -83,7 +83,7 @@ enum NPCIDs FATIMA, // 101 WARDEN, GORDON, - GABBY, + ENRICO, //GABBY, ERNEST, FRED, MADAME, diff --git a/Tactical/Turn Based Input.cpp b/Tactical/Turn Based Input.cpp index 7aaac7c0..39406299 100644 --- a/Tactical/Turn Based Input.cpp +++ b/Tactical/Turn Based Input.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #include "Language Defines.h" @@ -2683,8 +2684,10 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) break; case INSERT: - - GoIntoOverheadMap(); + + // WANNE 2: commented this out, because the interface panel is not correctly redrawn! + // I do not know the bug ;( + //GoIntoOverheadMap(); break; case END: diff --git a/Tactical/Weapons.cpp b/Tactical/Weapons.cpp index 5852654f..e8aaeb45 100644 --- a/Tactical/Weapons.cpp +++ b/Tactical/Weapons.cpp @@ -3372,7 +3372,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, UINT16 sGridNo, UINT8 ubAimTime iChance -= iPenalty; } - sDistVis = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, 0 ); + sDistVis = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, 0, pSoldier ); // give some leeway to allow people to spot for each other... // use distance limitation for LOS routine of 2 x maximum distance EVER visible, so that we get accurate diff --git a/Tactical/opplist.cpp b/Tactical/opplist.cpp index 2d844cbf..38d94e24 100644 --- a/Tactical/opplist.cpp +++ b/Tactical/opplist.cpp @@ -785,7 +785,6 @@ 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!) @@ -840,6 +839,7 @@ 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; + } @@ -997,7 +997,7 @@ INT16 MaxDistanceVisible( void ) return( STRAIGHT * 2 ); } -INT16 DistanceVisible( SOLDIERTYPE *pSoldier, INT8 bFacingDir, INT8 bSubjectDir, INT16 sSubjectGridNo, INT8 bLevel ) +INT16 DistanceVisible( SOLDIERTYPE *pSoldier, INT8 bFacingDir, INT8 bSubjectDir, INT16 sSubjectGridNo, INT8 bLevel, SOLDIERTYPE *pOther ) { INT16 sDistVisible; INT8 bLightLevel; @@ -1028,6 +1028,7 @@ 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(); @@ -1074,8 +1075,26 @@ INT16 DistanceVisible( SOLDIERTYPE *pSoldier, INT8 bFacingDir, INT8 bSubjectDir, // now reduce based on light level; SHADE_MIN is the define for the // highest number the light can be - bLightLevel = LightTrueLevel(sSubjectGridNo, bLevel); + // If we're about to ask for a light level for a location outside of our + // valid map references then use the ambient light level instead. + if(0 > sSubjectGridNo || sSubjectGridNo > WORLD_MAX) + { + if(pSoldier != pOther) + { + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("113/UC Warning! Tried to detect the light level when character %ls[%d] at gridno %d tries to look for character %ls[%d] who outside of the valid map (gridno %d). Assigning default %d", + pSoldier->name, pSoldier->ubID, pSoldier->sGridNo, pOther->name, pOther->ubID, pOther->sGridNo, ubAmbientLightLevel)); + } + else + { + DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("113/UC Warning! Tried to detect the light level when character %ls[%d] looks at a location outside of the valid map (gridno %d). Assigning default %d", + pSoldier->name, pSoldier->ubID, pSoldier->sGridNo, ubAmbientLightLevel)); + } + } + else + { + bLightLevel = LightTrueLevel(sSubjectGridNo, bLevel); + } // Snap: I think this was intended to give maximum visibility to targets with muzzle flash... // Corrected accordingly: @@ -1150,7 +1169,7 @@ void EndMuzzleFlash( SOLDIERTYPE * pSoldier ) { if ( pOtherSoldier->sGridNo != NOWHERE ) { - if ( PythSpacesAway( pOtherSoldier->sGridNo, pSoldier->sGridNo ) > DistanceVisible( pOtherSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, pSoldier->sGridNo, pSoldier->bLevel ) ) + if ( PythSpacesAway( pOtherSoldier->sGridNo, pSoldier->sGridNo ) > DistanceVisible( pOtherSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, pSoldier->sGridNo, pSoldier->bLevel, pSoldier ) ) { // if this guy can no longer see us, change to seen this turn HandleManNoLongerSeen( pOtherSoldier, pSoldier, &(pOtherSoldier->bOppList[ pSoldier->ubID ]), &(gbPublicOpplist[ pOtherSoldier->bTeam ][ pSoldier->ubID ] ) ); @@ -1401,7 +1420,6 @@ 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)); @@ -1439,6 +1457,7 @@ void ManLooksForOtherTeams(SOLDIERTYPE *pSoldier) } } } + } void HandleManNoLongerSeen( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pOpponent, INT8 * pPersOL, INT8 * pbPublOL ) @@ -1531,7 +1550,6 @@ INT16 ManLooksForMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, UINT8 ubCall INT16 sDistVisible,sDistAway; INT8 *pPersOL,*pbPublOL; - /* if (ptr->guynum >= NOBODY) { @@ -1575,8 +1593,6 @@ 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 ) { @@ -1680,15 +1696,13 @@ 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) { bAware = TRUE; // then we look for him full viewing distance in EVERY direction - sDistVisible = DistanceVisible(pSoldier, DIRECTION_IRRELEVANT, 0, pOpponent->sGridNo, pOpponent->bLevel ); - + sDistVisible = DistanceVisible(pSoldier, DIRECTION_IRRELEVANT, 0, pOpponent->sGridNo, pOpponent->bLevel, pOpponent ); //if (pSoldier->ubID == 0) //sprintf(gDebugStr,"ALREADY KNOW: ME %d him %d val %d",pSoldier->ubID,pOpponent->ubID,pSoldier->bOppList[pOpponent->ubID]); } @@ -1699,8 +1713,7 @@ INT16 ManLooksForMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, UINT8 ubCall // BIG NOTE: must use desdir instead of direction, since in a projected // situation, the direction may still be changing if it's one of the first // few animation steps when this guy's turn to do his stepped look comes up - sDistVisible = DistanceVisible(pSoldier,pSoldier->bDesiredDirection,bDir, pOpponent->sGridNo, pOpponent->bLevel ); - + sDistVisible = DistanceVisible(pSoldier,pSoldier->bDesiredDirection,bDir, pOpponent->sGridNo, pOpponent->bLevel, pOpponent ); //if (pSoldier->ubID == 0) //sprintf(gDebugStr,"dist visible %d: my dir %d to him %d",sDistVisible,pSoldier->bDesiredDirection,bDir); } @@ -1712,7 +1725,6 @@ INT16 ManLooksForMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, UINT8 ubCall DebugMsg( TOPIC_JA2OPPLIST, DBG_LEVEL_3, String( "MANLOOKSFORMAN: ID %d(%S) to ID %d: sDistAway %d sDistVisible %d",pSoldier->ubID,pSoldier->name,pOpponent->ubID,sDistAway,sDistVisible) ); #endif - // if we see close enough to see the soldier if (sDistAway <= sDistVisible) { @@ -1779,8 +1791,6 @@ INT16 ManLooksForMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, UINT8 ubCall } - - return(bSuccess); } @@ -5520,7 +5530,7 @@ void HearNoise(SOLDIERTYPE *pSoldier, UINT8 ubNoiseMaker, UINT16 sGridNo, INT8 b } } - sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel ); + sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel, pSoldier ); if ( fMuzzleFlash ) { @@ -6370,7 +6380,7 @@ void NoticeUnseenAttacker( SOLDIERTYPE * pAttacker, SOLDIERTYPE * pDefender, INT } } - ubTileSightLimit = (UINT8) DistanceVisible( pDefender, DIRECTION_IRRELEVANT, 0, pAttacker->sGridNo, pAttacker->bLevel ); + ubTileSightLimit = (UINT8) DistanceVisible( pDefender, DIRECTION_IRRELEVANT, 0, pAttacker->sGridNo, pAttacker->bLevel, pAttacker ); if (SoldierToSoldierLineOfSightTest( pDefender, pAttacker, ubTileSightLimit, TRUE ) != 0) { fSeesAttacker = TRUE; @@ -6489,7 +6499,7 @@ void CheckForAlertWhenEnemyDies( SOLDIERTYPE * pDyingSoldier ) // distance we "see" then depends on the direction he is located from us bDir = atan8(pSoldier->sX,pSoldier->sY,pDyingSoldier->sX,pDyingSoldier->sY); - sDistVisible = DistanceVisible( pSoldier, pSoldier->bDesiredDirection, bDir, pDyingSoldier->sGridNo, pDyingSoldier->bLevel ); + sDistVisible = DistanceVisible( pSoldier, pSoldier->bDesiredDirection, bDir, pDyingSoldier->sGridNo, pDyingSoldier->bLevel, pDyingSoldier ); sDistAway = PythSpacesAway( pSoldier->sGridNo, pDyingSoldier->sGridNo ); // if we see close enough to see the soldier @@ -6630,7 +6640,7 @@ INT8 GetHighestVisibleWatchedLoc( UINT8 ubID ) { if ( gsWatchedLoc[ ubID ][ bLoop ] != NOWHERE && gubWatchedLocPoints[ ubID ][ bLoop ] > bHighestPoints ) { - sDistVisible = DistanceVisible( MercPtrs[ ubID ], DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, gsWatchedLoc[ ubID ][ bLoop ], gbWatchedLocLevel[ ubID ][ bLoop ] ); + sDistVisible = DistanceVisible( MercPtrs[ ubID ], DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, gsWatchedLoc[ ubID ][ bLoop ], gbWatchedLocLevel[ ubID ][ bLoop ], MercPtrs[ubID] ); // look at standing height if ( SoldierTo3DLocationLineOfSightTest( MercPtrs[ ubID ], gsWatchedLoc[ ubID ][ bLoop ], gbWatchedLocLevel[ ubID ][ bLoop ], 3, (UINT8) sDistVisible, TRUE ) ) { diff --git a/Tactical/opplist.h b/Tactical/opplist.h index 245c2e9a..da6d9e94 100644 --- a/Tactical/opplist.h +++ b/Tactical/opplist.h @@ -100,7 +100,7 @@ void AddOneOpponent(SOLDIERTYPE *pSoldier); void RemoveOneOpponent(SOLDIERTYPE *pSoldier); void UpdatePersonal(SOLDIERTYPE *pSoldier, UINT8 ubID, INT8 bNewOpplist, INT16 sGridno, INT8 bLevel); INT16 MaxDistanceVisible( void ); -INT16 DistanceVisible( SOLDIERTYPE *pSoldier, INT8 bFacingDir, INT8 bSubjectDir, INT16 sSubjectGridNo, INT8 bLevel ); +INT16 DistanceVisible( SOLDIERTYPE *pSoldier, INT8 bFacingDir, INT8 bSubjectDir, INT16 sSubjectGridNo, INT8 bLevel, SOLDIERTYPE *pOther ); void ResetLastKnownLocs(SOLDIERTYPE *ptr); void RecalculateOppCntsDueToNoLongerNeutral( SOLDIERTYPE * pSoldier ); diff --git a/TacticalAI/AIMain.cpp b/TacticalAI/AIMain.cpp index d2720684..de696948 100644 --- a/TacticalAI/AIMain.cpp +++ b/TacticalAI/AIMain.cpp @@ -2739,7 +2739,7 @@ void ManChecksOnFriends(SOLDIERTYPE *pSoldier) if (pFriend->ubID == pSoldier->ubID) continue; // next merc - sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, pFriend->sGridNo, pFriend->bLevel ); + sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, pFriend->sGridNo, pFriend->bLevel, pFriend ); // if we can see far enough to see this friend if (PythSpacesAway(pSoldier->sGridNo,pFriend->sGridNo) <= sDistVisible) { diff --git a/TacticalAI/CreatureDecideAction.cpp b/TacticalAI/CreatureDecideAction.cpp index 4b1fe33e..9025a23e 100644 --- a/TacticalAI/CreatureDecideAction.cpp +++ b/TacticalAI/CreatureDecideAction.cpp @@ -846,7 +846,7 @@ INT8 CreatureDecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK) // if soldier is not already facing in that direction, // and the opponent is close enough that he could possibly be seen // note, have to change this to use the level returned from ClosestKnownOpponent - sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sClosestOpponent, 0 ); + sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sClosestOpponent, 0, pSoldier ); if ((pSoldier->bDirection != ubOpponentDir) && (PythSpacesAway(pSoldier->sGridNo,sClosestOpponent) <= sDistVisible)) { diff --git a/TacticalAI/DecideAction.cpp b/TacticalAI/DecideAction.cpp index d6a5e9ae..01b19bc6 100644 --- a/TacticalAI/DecideAction.cpp +++ b/TacticalAI/DecideAction.cpp @@ -3042,7 +3042,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: radio red alert?"); // if soldier is not already facing in that direction, // and the opponent is close enough that he could possibly be seen // note, have to change this to use the level returned from ClosestKnownOpponent - sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sClosestOpponent, 0 ); + sDistVisible = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sClosestOpponent, 0, pSoldier ); if ((pSoldier->bDirection != ubOpponentDir) && (PythSpacesAway(pSoldier->sGridNo,sClosestOpponent) <= sDistVisible)) { diff --git a/TileEngine/Buildings.cpp b/TileEngine/Buildings.cpp index a9327a96..02add2fc 100644 --- a/TileEngine/Buildings.cpp +++ b/TileEngine/Buildings.cpp @@ -36,7 +36,9 @@ BUILDING * CreateNewBuilding( UINT8 * pubBuilding ) BUILDING * GenerateBuilding( INT16 sDesiredSpot ) { + UINT32 uiLoop; + UINT32 uiLoop2; INT16 sTempGridNo, sNextTempGridNo, sVeryTemporaryGridNo; INT16 sStartGridNo, sCurrGridNo, sPrevGridNo = NOWHERE, sRightGridNo; INT8 bDirection, bTempDirection; @@ -106,9 +108,9 @@ BUILDING * GenerateBuilding( INT16 sDesiredSpot ) gpWorldLevelData[ sStartGridNo ].ubExtFlags[0] |= MAPELEMENT_EXT_ROOFCODE_VISITED; - while( 1 ) + uiLoop2 = 0; + while(uiLoop2 < WORLD_MAX) { - // if point to (2 clockwise) is not part of building and is not visited, // or is starting point, turn! sRightGridNo = NewGridNo( sCurrGridNo, DirectionInc( gTwoCDirection[ bDirection ] ) ); @@ -202,8 +204,6 @@ BUILDING * GenerateBuilding( INT16 sDesiredSpot ) { gpWorldLevelData[ sCurrGridNo ].ubExtFlags[0] |= MAPELEMENT_EXT_ROOFCODE_VISITED; - //DebugMsg( TOPIC_JA2AI , DBG_LEVEL_3 , String("Building info set at %d to %d", sCurrGridNo, ubBuildingID )); - gubBuildingInfo[ sCurrGridNo ] = ubBuildingID; // consider this location as possible climb gridno @@ -323,8 +323,22 @@ BUILDING * GenerateBuilding( INT16 sDesiredSpot ) } } - + uiLoop2++; } + // If we've run out of loop before we've run out of building, then there is + // something that has gone pear shaped + if(uiLoop2 >= WORLD_MAX) + { + UINT8 x = 0; + UINT8 y = 0; + while((sDesiredSpot - ((y + 1) * 160)) >= 0) + { + y++; + } + x = sDesiredSpot - (y * 160); + DebugMsg (TOPIC_JA2,DBG_LEVEL_2,String( "113/UC Warning! Building Walk Algorithm has covered the entire map! Building %d located at [%d,%d] must be bogus.", ubBuildingID, x, y )); + } + // at end could prune # of locations if there are too many @@ -338,7 +352,6 @@ BUILDING * GenerateBuilding( INT16 sDesiredSpot ) RefreshScreen( NULL ); #endif */ - return( pBuilding ); } @@ -415,7 +428,6 @@ void GenerateBuildings( void ) // search through world // for each location in a room try to find building info - for ( uiLoop = 0; uiLoop < WORLD_MAX; uiLoop++ ) { if ( (gubWorldRoomInfo[ uiLoop ] != NO_ROOM) && (gubBuildingInfo[ uiLoop ] == NO_BUILDING) && (FindStructure( (INT16) uiLoop, STRUCTURE_NORMAL_ROOF ) != NULL) ) diff --git a/TileEngine/Radar Screen.cpp b/TileEngine/Radar Screen.cpp index b5d069e9..daac8870 100644 --- a/TileEngine/Radar Screen.cpp +++ b/TileEngine/Radar Screen.cpp @@ -246,11 +246,15 @@ void RadarRegionButtonCallback( MOUSE_REGION * pRegion, INT32 iReason ) { if ( !InOverheadMap( ) ) { - GoIntoOverheadMap( ); + // WANNE 2 + if (fDisplayOverheadMap == TRUE) + GoIntoOverheadMap( ); } else { - KillOverheadMap(); + // WANNE 2 + if (fDisplayOverheadMap == TRUE) + KillOverheadMap(); } } } @@ -644,9 +648,10 @@ BOOLEAN CreateDestroyMouseRegionsForSquadList( void ) CHECKF(AddVideoObject(&VObjectDesc, &uiHandle)); GetVideoObject(&hHandle, uiHandle); - BltVideoObject( guiSAVEBUFFER , hHandle, 0,(INTERFACE_WIDTH - 102 - 1), 0 + gsVIEWPORT_END_Y, VO_BLT_SRCTRANSPARENCY,NULL ); - - RestoreExternBackgroundRect( (INTERFACE_WIDTH - 102), gsVIEWPORT_END_Y, (SCREEN_WIDTH - 538 ),( INT16 ) ( SCREEN_HEIGHT - gsVIEWPORT_END_Y ) ); + + + BltVideoObject( guiSAVEBUFFER , hHandle, 0,(SCREEN_WIDTH - 102 - 1), gsVIEWPORT_END_Y, VO_BLT_SRCTRANSPARENCY,NULL ); + RestoreExternBackgroundRect ((SCREEN_WIDTH - 102 - 1), gsVIEWPORT_END_Y, 102,( INT16 ) ( SCREEN_HEIGHT - gsVIEWPORT_END_Y ) ); for( sCounter = 0; sCounter < NUMBER_OF_SQUADS; sCounter++ ) { diff --git a/TileEngine/Radar Screen.h b/TileEngine/Radar Screen.h index 2bcb07ec..f0f64cb3 100644 --- a/TileEngine/Radar Screen.h +++ b/TileEngine/Radar Screen.h @@ -1,3 +1,4 @@ +// WANNE 2 #ifndef __RADAR_SCREEN_H #define __RADAR_SCREEN_H @@ -9,13 +10,14 @@ void RadarRegionButtonCallback( MOUSE_REGION * pRegion, INT32 iReason ); BOOLEAN LoadRadarScreenBitmap( CHAR8 * aFilename ); +// WANNE 2 // RADAR WINDOW DEFINES -#define RADAR_WINDOW_X 543 +#define RADAR_WINDOW_X (SCREEN_WIDTH - 97) //543 #define RADAR_WINDOW_TM_Y INTERFACE_START_Y + 13 #define RADAR_WINDOW_SM_Y INV_INTERFACE_START_Y + 13 #define RADAR_WINDOW_WIDTH 88 #define RADAR_WINDOW_HEIGHT 44 -#define RADAR_WINDOW_STRAT_Y 373 +#define RADAR_WINDOW_STRAT_Y (SCREEN_HEIGHT - 107) //373 BOOLEAN InitRadarScreen( ); void RenderRadarScreen( ); diff --git a/TileEngine/Tactical Placement GUI.cpp b/TileEngine/Tactical Placement GUI.cpp index dfece930..b9b433a9 100644 --- a/TileEngine/Tactical Placement GUI.cpp +++ b/TileEngine/Tactical Placement GUI.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "TileEngine All.h" #include "PreBattle Interface.h" @@ -563,7 +564,9 @@ void RenderTacticalPlacementGUI() { gTPClipRect.iLeft = iOffsetHorizontal; gTPClipRect.iTop = iOffsetVertical; - gTPClipRect.iRight = iOffsetHorizontal + 640; + // WANNE 2 + //gTPClipRect.iRight = iOffsetHorizontal + 640; + gTPClipRect.iRight = iOffsetHorizontal + 635; gTPClipRect.iBottom = iOffsetVertical + 320; switch( gMercPlacement[ gbCursorMercID ].ubStrategicInsertionCode ) { diff --git a/TileEngine/overhead map.cpp b/TileEngine/overhead map.cpp index 982a396f..3b2e547b 100644 --- a/TileEngine/overhead map.cpp +++ b/TileEngine/overhead map.cpp @@ -402,7 +402,7 @@ void HandleOverheadMap( ) InitNewOverheadDB( gubSmTileNum ); gfSmTileLoaded = TRUE; } - + // restore background rects RestoreBackgroundRects( ); @@ -544,12 +544,15 @@ BOOLEAN InOverheadMap( ) } void GoIntoOverheadMap( ) -{ + { VOBJECT_DESC VObjectDesc; HVOBJECT hVObject; gfInOverheadMap = TRUE; + // WANNE 2 NEW + //RestoreExternBackgroundRect( INTERFACE_START_X, INTERFACE_START_Y, SCREEN_WIDTH, INTERFACE_HEIGHT ); + // Overview map should be centered in the middle of the tactical screen. iOffsetHorizontal = (SCREEN_WIDTH / 2) - (640 / 2); // Horizontal start postion of the overview map iOffsetVertical = (SCREEN_HEIGHT - 160) / 2 - 160; // Vertical start position of the overview map diff --git a/TileEngine/physics.cpp b/TileEngine/physics.cpp index 0e37e296..bc11b48b 100644 --- a/TileEngine/physics.cpp +++ b/TileEngine/physics.cpp @@ -1667,6 +1667,7 @@ FLOAT CalculateObjectTrajectory( INT16 sTargetZ, OBJECTTYPE *pItem, vector_3 *vP REAL_OBJECT *pObject; FLOAT dDiffX, dDiffY; INT16 sGridNo; + //int cnt=0; if ( psFinalGridNo ) { @@ -1692,10 +1693,13 @@ FLOAT CalculateObjectTrajectory( INT16 sTargetZ, OBJECTTYPE *pItem, vector_3 *vP pObject->fTestPositionNotSet = TRUE; pObject->fVisible = FALSE; + // WANNE 2 // Alrighty, move this beast until it dies.... - while( pObject->fAlive ) + while( pObject->fAlive) { - DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateObjectTrajectory: calling simulateobject - this object never fucking dies!!!!"); + //cnt = cnt + 1; + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateObjectTrajectory: calling SIMULATEobject - this object never fucking dies!!!!"); + //DebugMsg (TOPIC_JA2,DBG_LEVEL_3, String( "Counter: %d", cnt)); SimulateObject( pObject, (float)DELTA_T ); } diff --git a/TileEngine/physics_v113.cpp b/TileEngine/physics_v113.cpp new file mode 100644 index 00000000..0e37e296 --- /dev/null +++ b/TileEngine/physics_v113.cpp @@ -0,0 +1,2673 @@ +#ifdef PRECOMPILEDHEADERS + #include "TileEngine All.h" +#else + #include "physics.h" + #include "wcheck.h" + #include "timer control.h" + #include "isometric utils.h" + #include "los.h" + #include "worldman.h" + #include "event pump.h" + #include "Sound Control.h" + #include "soldier control.h" + #include "interface.h" + #include "interface items.h" + #include "weapons.h" + #include "explosion control.h" + #include "Debug Control.h" + #include "tile animation.h" + #include "message.h" + #include "weapons.h" + #include "structure wrap.h" + #include "physics.h" + #include "overhead.h" + #include "animation control.h" + #include "text.h" + #include "Random.h" + #include "lighteffects.h" + #include "opplist.h" + #include "World Items.h" + #include "environment.h" +#endif + +#include "Campaign.h" +#include "SkillCheck.h" + +#define NO_TEST_OBJECT 0 +#define TEST_OBJECT_NO_COLLISIONS 1 +#define TEST_OBJECT_ANY_COLLISION 2 +#define TEST_OBJECT_NOTWALLROOF_COLLISIONS 3 + +#define OUTDOORS_START_ANGLE (FLOAT)( PI/4 ) +#define INDOORS_START_ANGLE (FLOAT)( PI/30 ) +//#define INDOORS_START_ANGLE (FLOAT)( 0 ) +#define GLAUNCHER_START_ANGLE (FLOAT)( PI/8 ) +#define GLAUNCHER_HIGHER_LEVEL_START_ANGLE (FLOAT)( PI/6 ) + +#define GET_THROW_HEIGHT( l ) (INT16)( ( l * 256 ) ) +//#define GET_SOLDIER_THROW_HEIGHT( l ) (INT16)( ( l * 256 ) + STANDING_HEIGHT ) +// ATE: Commented out part to provide a more accurate start height +#define GET_SOLDIER_THROW_HEIGHT( l ) (INT16)( ( l * 256 ) + CROUCHED_HEIGHT ) + +#define GET_OBJECT_LEVEL( z ) ( (INT8)( ( z + 10 ) / HEIGHT_UNITS ) ) +//#define OBJECT_DETONATE_ON_IMPACT( o ) ( ( o->Obj.usItem == MORTAR_SHELL ) ) // && ( o->ubActionCode == THROW_ARM_ITEM || pObject->fTestObject ) ) +#define OBJECT_DETONATE_ON_IMPACT( o ) ( ( Item[o->Obj.usItem].usItemClass == IC_BOMB ) ) // && ( o->ubActionCode == THROW_ARM_ITEM || pObject->fTestObject ) ) + + +#define MAX_INTEGRATIONS 8 + +#define TIME_MULTI 1.8 + +//#define TIME_MULTI 2.2 + + +#define DELTA_T ( 1.0 * TIME_MULTI ) + + +#define GRAVITY ( 9.8 * 2.5 ) +//#define GRAVITY ( 9.8 * 2.8 ) + + +REAL_OBJECT ObjectSlots[ NUM_OBJECT_SLOTS ]; +UINT32 guiNumObjectSlots = 0; +BOOLEAN fDampingActive = FALSE; +//real Kdl = (float)0.5; // LINEAR DAMPENING ( WIND RESISTANCE ) +real Kdl = (float)( 0.1 * TIME_MULTI ); // LINEAR DAMPENING ( WIND RESISTANCE ) + +#define EPSILONV 0.5 +#define EPSILONP (real)0.01 +#define EPSILONPZ 3 + +#define CALCULATE_OBJECT_MASS( m ) ( (float)( m * 2 ) ) +#define SCALE_VERT_VAL_TO_HORZ( f ) ( ( f / HEIGHT_UNITS ) * CELL_X_SIZE ) +#define SCALE_HORZ_VAL_TO_VERT( f ) ( ( f / CELL_X_SIZE ) * HEIGHT_UNITS ) + +void SimulateObject( REAL_OBJECT *pObject, real deltaT ); + +void CheckForObjectHittingMerc( REAL_OBJECT *pObject, UINT16 usStructureID ); +extern void DoGenericHit( SOLDIERTYPE *pSoldier, UINT8 ubSpecial, INT16 bDirection ); + + +BOOLEAN PhysicsUpdateLife( REAL_OBJECT *pObject, real DeltaTime ); +BOOLEAN PhysicsComputeForces( REAL_OBJECT *pObject ); +BOOLEAN PhysicsIntegrate( REAL_OBJECT *pObject, real DeltaTime ); +BOOLEAN PhysicsMoveObject( REAL_OBJECT *pObject ); +BOOLEAN PhysicsCheckForCollisions( REAL_OBJECT *pObject, INT32 *piCollisionID ); +void PhysicsResolveCollision( REAL_OBJECT *pObject, vector_3 *pVelocity, vector_3 *pNormal, real CoefficientOfRestitution ); +void PhysicsDeleteObject( REAL_OBJECT *pObject ); +BOOLEAN PhysicsHandleCollisions( REAL_OBJECT *pObject, INT32 *piCollisionID, real DeltaTime ); +FLOAT CalculateForceFromRange( INT16 sRange, FLOAT dDegrees ); + +UINT16 RandomGridFromRadius( INT16 sSweetGridNo, INT8 ubMinRadius, INT8 ubMaxRadius ); + + +void HandleArmedObjectImpact( REAL_OBJECT *pObject ); +void ObjectHitWindow( INT16 sGridNo, UINT16 usStructureID, BOOLEAN fBlowWindowSouth, BOOLEAN fLargeForce ); +FLOAT CalculateObjectTrajectory( INT16 sTargetZ, OBJECTTYPE *pItem, vector_3 *vPosition, vector_3 *vForce, INT16 *psFinalGridNo ); +vector_3 FindBestForceForTrajectory( INT16 sSrcGridNo, INT16 sGridNo,INT16 sStartZ, INT16 sEndZ, real dzDegrees, OBJECTTYPE *pItem, INT16 *psGridNo, FLOAT *pzMagForce ); +INT32 ChanceToGetThroughObjectTrajectory( INT16 sTargetZ, OBJECTTYPE *pItem, vector_3 *vPosition, vector_3 *vForce, INT16 *psFinalGridNo, INT8 *pbLevel, BOOLEAN fFromUI ); +FLOAT CalculateSoldierMaxForce( SOLDIERTYPE *pSoldier, FLOAT dDegrees, OBJECTTYPE *pObject, BOOLEAN fArmed ); +BOOLEAN AttemptToCatchObject( REAL_OBJECT *pObject ); +BOOLEAN CheckForCatchObject( REAL_OBJECT *pObject ); +BOOLEAN DoCatchObject( REAL_OBJECT *pObject ); +BOOLEAN CheckForCatcher( REAL_OBJECT *pObject, UINT16 usStructureID ); + + +/// OBJECT POOL FUNCTIONS +INT32 GetFreeObjectSlot(void) +{ + UINT32 uiCount; + + for(uiCount=0; uiCount < guiNumObjectSlots; uiCount++) + { + if(( ObjectSlots[uiCount].fAllocated == FALSE ) ) + return((INT32)uiCount); + } + + if(guiNumObjectSlots < NUM_OBJECT_SLOTS ) + return((INT32)guiNumObjectSlots++); + + return(-1); +} + + +void RecountObjectSlots(void) +{ + INT32 uiCount; + + for(uiCount=guiNumObjectSlots-1; (uiCount >=0) ; uiCount--) + { + if( ( ObjectSlots[uiCount].fAllocated ) ) + { + guiNumObjectSlots=(UINT32)(uiCount+1); + return; + } + } + + guiNumObjectSlots = 0; +} + + +INT32 CreatePhysicalObject( OBJECTTYPE *pGameObj, real dLifeLength, real xPos, real yPos, real zPos, real xForce, real yForce, real zForce, UINT8 ubOwner, UINT8 ubActionCode, UINT32 uiActionData ) +{ + INT32 iObjectIndex; + FLOAT mass; + REAL_OBJECT *pObject; + + if( ( iObjectIndex = GetFreeObjectSlot() )==(-1) ) + return(-1); + + pObject = &( ObjectSlots[ iObjectIndex ] ); + + memset( pObject, 0, sizeof( REAL_OBJECT ) ); + + // OK, GET OBJECT DATA AND COPY + memcpy( &(pObject->Obj), pGameObj, sizeof( OBJECTTYPE ) ); + + // Get mass + mass = CALCULATE_OBJECT_MASS( Item[pGameObj->usItem ].ubWeight ); + + // If mass is z, make it something! + if ( mass == 0 ) + { + mass = 10; + } + + // OK, mass determines the smoothness of the physics integration + // For gameplay, we will use mass for maybe max throw distance + mass = 60; + + // Set lifelength + pObject->dLifeLength = dLifeLength; + + pObject->fAllocated = TRUE; + pObject->fAlive = TRUE; + pObject->fApplyFriction = FALSE; + pObject->iSoundID = NO_SAMPLE; + + // Set values + pObject->OneOverMass = 1 / mass; + pObject->Position.x = xPos; + pObject->Position.y = yPos; + pObject->Position.z = zPos; + pObject->fVisible = TRUE; + pObject->ubOwner = ubOwner; + pObject->ubActionCode = ubActionCode; + pObject->uiActionData = uiActionData; + pObject->fDropItem = TRUE; + pObject->ubLastTargetTakenDamage = NOBODY; + + pObject->fFirstTimeMoved = TRUE; + + pObject->InitialForce.x = SCALE_VERT_VAL_TO_HORZ( xForce ); + pObject->InitialForce.y = SCALE_VERT_VAL_TO_HORZ( yForce ); + pObject->InitialForce.z = zForce ; + + pObject->InitialForce = VDivScalar( &(pObject->InitialForce), (float)TIME_MULTI ); + pObject->InitialForce = VMultScalar( &(pObject->InitialForce), 1.5 ); + + + // Calculate gridNo + pObject->sGridNo = MAPROWCOLTOPOS( ( (INT16)yPos / CELL_Y_SIZE ), ( (INT16)xPos / CELL_X_SIZE ) ); + pObject->iID = iObjectIndex; + pObject->pNode = NULL; + pObject->pShadow = NULL; + + // If gridno not equal to NOWHERE, use sHeight of alnd.... + if ( pObject->sGridNo != NOWHERE ) + { + pObject->Position.z += CONVERT_PIXELS_TO_HEIGHTUNITS( gpWorldLevelData[ pObject->sGridNo ].sHeight ); + pObject->EndedWithCollisionPosition.z += CONVERT_PIXELS_TO_HEIGHTUNITS( gpWorldLevelData[ pObject->sGridNo ].sHeight ); + } + + PhysicsDebugMsg( String( "NewPhysics Object") ); + + return( iObjectIndex ); +} + + +BOOLEAN RemoveObjectSlot( INT32 iObject ) +{ + CHECKF( iObject < NUM_OBJECT_SLOTS ); + + ObjectSlots[iObject].fAllocated=FALSE; + + RecountObjectSlots(); + + return( TRUE ); +} + + +void SimulateWorld( ) +{ + UINT32 cnt; + REAL_OBJECT *pObject; + + + if ( COUNTERDONE( PHYSICSUPDATE ) ) + { + RESETCOUNTER( PHYSICSUPDATE ); + + for( cnt = 0;cnt < guiNumObjectSlots; cnt++) + { + // CHECK FOR ALLOCATED + if( ObjectSlots[ cnt ].fAllocated ) + { + // Get object + pObject = &( ObjectSlots[ cnt ] ); + + SimulateObject( pObject, (real)DELTA_T ); + } + } + } +} + +void RemoveAllPhysicsObjects( ) +{ + UINT32 cnt; + + for( cnt = 0;cnt < guiNumObjectSlots; cnt++) + { + // CHECK FOR ALLOCATED + if( ObjectSlots[ cnt ].fAllocated ) + { + PhysicsDeleteObject( &(ObjectSlots[ cnt ]) ); + } + } +} + + +void SimulateObject( REAL_OBJECT *pObject, real deltaT ) +{ + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"SimulateObject"); + real DeltaTime = 0; + real CurrentTime = 0; + real TargetTime = DeltaTime; + INT32 iCollisionID; + BOOLEAN fEndThisObject = FALSE; + + if ( !PhysicsUpdateLife( pObject, (float)deltaT ) ) + { +// DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"SimulateObject: don't update life, returning"); + return; + } + +// DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"SimulateObject: check life"); + if ( pObject->fAlive ) + { + CurrentTime = 0; + TargetTime = (float)deltaT; + + //DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"SimulateObject: do subtime"); + // Do subtime here.... + DeltaTime = (float)deltaT / (float)10; + + if ( !PhysicsComputeForces( pObject ) ) + { +// DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"SimulateObject: couldn't compute forces"); + return; + } + + while( CurrentTime < TargetTime ) + { +//MADD TO KAIDEN: HERE IS THE PROBLEM: For some reason fEndThisObject is never set to true +// DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("SimulateObject: in loop while CurrentTime < TargetTime: %d < %d",CurrentTime,TargetTime)); + + if ( !PhysicsIntegrate( pObject, DeltaTime ) ) + { + fEndThisObject = TRUE; + break; + } + + if ( !PhysicsHandleCollisions( pObject, &iCollisionID, DeltaTime ) ) + { + fEndThisObject = TRUE; + break; + } + + if ( iCollisionID != COLLISION_NONE ) + { + break; + } + + CurrentTime += DeltaTime; + } + + //DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"SimulateObject: check if ending this object"); + if ( fEndThisObject ) + { + //DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"SimulateObject: object ended, returning"); + return; + } + + //DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"SimulateObject: try moving the object"); + if ( !PhysicsMoveObject( pObject ) ) + { + //DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"SimulateObject: couldn't move object, returning"); + return; + } + + } +} + + +BOOLEAN PhysicsComputeForces( REAL_OBJECT *pObject ) +{ + vector_3 vTemp; + + // Calculate forces + pObject->Force = VSetEqual( &(pObject->InitialForce ) ); + + // Note: Only apply gravity if we are not resting on some structure surface + if ( !pObject->fZOnRest ) + { + pObject->Force.z -= (real)GRAVITY; + } + + // Set intial force to zero + pObject->InitialForce = VMultScalar( &(pObject->InitialForce ), 0 ); + + if ( pObject->fApplyFriction ) + { + vTemp = VMultScalar( &(pObject->Velocity), -pObject->AppliedMu ); + pObject->Force = VAdd( &(vTemp), &(pObject->Force) ); + + pObject->fApplyFriction = FALSE; + } + + if( fDampingActive ) + { + vTemp = VMultScalar( &(pObject->Velocity), -Kdl ); + pObject->Force = VAdd( &(vTemp), &(pObject->Force) ); + + } + + return( TRUE ); +} + +BOOLEAN PhysicsUpdateLife( REAL_OBJECT *pObject, real DeltaTime ) +{ + UINT8 bLevel = 0; + + pObject->dLifeSpan += DeltaTime; + + // End life if time has ran out or we are stationary + if ( pObject->dLifeLength != -1 ) + { + if ( pObject->dLifeSpan > pObject->dLifeLength ) + { + pObject->fAlive = FALSE; + } + + } + + // End life if we are out of bounds.... + if ( !GridNoOnVisibleWorldTile( pObject->sGridNo ) ) + { + pObject->fAlive = FALSE; + } + + if ( !pObject->fAlive ) + { + if ( !pObject->fTestObject ) + { + int i = 0; + } + + // ATE: OK, adjust gridno based on where we ended and if we hit any walls.... + { + // Check for SW wall... + real remainder; + + remainder = (float)fmod( pObject->Position.x, CELL_X_SIZE ); + + if ( remainder >= 9 ) + { + // DO we have a wall here? + if ( WallOrClosedDoorExistsOfTopRightOrientation( pObject->sGridNo ) ) + { + // Adjust forward 1! + pObject->sGridNo += 1; + } + } + + // Now SE wall + remainder = (float)fmod( pObject->Position.y, CELL_X_SIZE ); + + if ( remainder >= 9 ) + { + // DO we have a wall here? + if ( WallOrClosedDoorExistsOfTopLeftOrientation( pObject->sGridNo ) ) + { + // Adjust forward 1! + pObject->sGridNo += WORLD_COLS; + } + } + } + + pObject->fAlive = FALSE; + + if ( !pObject->fTestObject ) + { + if ( pObject->iSoundID != NO_SAMPLE ) + { + SoundStop( pObject->iSoundID ); + } + + if ( pObject->ubActionCode == THROW_ARM_ITEM && !pObject->fInWater ) + { + HandleArmedObjectImpact( pObject ); + } + else + { + // If we are in water, and we are a sinkable item... +// if ( !pObject->fInWater || !( Item[ pObject->Obj.usItem ].fFlags & ITEM_SINKS ) ) + if ( !pObject->fInWater || !( Item[ pObject->Obj.usItem ].sinks ) ) + { + if ( pObject->fDropItem ) + { + // ATE: If we have collided with roof last... + if ( pObject->iOldCollisionCode == COLLISION_ROOF ) + { + bLevel = 1; + } + + // ATE: Yet another hack here, to make sure things don't fall through roofs + if ( pObject->ubLastTargetTakenDamage != NOBODY ) + { + SOLDIERTYPE *pSoldier; + + pSoldier = MercPtrs[ pObject->ubLastTargetTakenDamage ]; + + bLevel = pSoldier->bLevel; + } + + // ATE; If an armed object, don't add.... + if ( pObject->ubActionCode != THROW_ARM_ITEM ) + { + AddItemToPool( pObject->sGridNo, &( pObject->Obj ), 1, bLevel, 0, -1 ); + } + } + } + } + + // Make impact noise.... + if ( Item[pObject->Obj.usItem].rock ) + { + MakeNoise( pObject->ubOwner, pObject->sGridNo, 0, gpWorldLevelData[ pObject->sGridNo ].ubTerrainID, (UINT8) (9 + PreRandom( 9 ) ), NOISE_ROCK_IMPACT ); + } + else if ( Item[ pObject->Obj.usItem ].usItemClass & IC_GRENADE ) + { + MakeNoise( pObject->ubOwner, pObject->sGridNo, 0, gpWorldLevelData[ pObject->sGridNo ].ubTerrainID, (UINT8) (9 + PreRandom( 9 ) ), NOISE_GRENADE_IMPACT ); + } + + if ( !pObject->fTestObject && pObject->iOldCollisionCode == COLLISION_GROUND ) + { + PlayJA2Sample( THROW_IMPACT_2, RATE_11025, SoundVolume( MIDVOLUME, pObject->sGridNo ), 1, SoundDir( pObject->sGridNo ) ); + } + + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Reducing attacker busy count..., PHYSICS OBJECT DONE effect gone off") ); + ReduceAttackBusyCount( pObject->ubOwner, FALSE ); + + // ATE: Handle end of animation... + if ( pObject->fCatchAnimOn ) + { + SOLDIERTYPE *pSoldier; + + pObject->fCatchAnimOn = FALSE; + + // Get intended target + pSoldier = MercPtrs[ pObject->uiActionData ]; + + // Catch anim..... + switch( gAnimControl[ pSoldier->usAnimState ].ubHeight ) + { + case ANIM_STAND: + + pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; + EVENT_InitNewSoldierAnim( pSoldier, END_CATCH, 0 , FALSE ); + break; + + case ANIM_CROUCH: + + pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; + EVENT_InitNewSoldierAnim( pSoldier, END_CROUCH_CATCH, 0 , FALSE ); + break; + } + + PlayJA2Sample( CATCH_OBJECT, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) ); + + } + } + + PhysicsDeleteObject( pObject ); + return( FALSE ); + } + + return( TRUE ); +} + + +BOOLEAN PhysicsIntegrate( REAL_OBJECT *pObject, real DeltaTime ) +{ + vector_3 vTemp; + + // Save old position + pObject->OldPosition = VSetEqual( &(pObject->Position) ); + pObject->OldVelocity = VSetEqual( &(pObject->Velocity) ); + + vTemp = VMultScalar( &(pObject->Velocity), DeltaTime ); + pObject->Position = VAdd( &(pObject->Position), &vTemp ); + + // Save test TargetPosition + if ( pObject->fTestPositionNotSet ) + { + pObject->TestTargetPosition = VSetEqual( &(pObject->Position) ); + } + + vTemp = VMultScalar( &(pObject->Force), ( DeltaTime * pObject->OneOverMass ) ); + pObject->Velocity = VAdd( &(pObject->Velocity), &vTemp ); + + if ( pObject->fPotentialForDebug ) + { + PhysicsDebugMsg( String( "Object %d: Force %f %f %f", pObject->iID, pObject->Force.x, pObject->Force.y, pObject->Force.z ) ); + PhysicsDebugMsg( String( "Object %d: Velocity %f %f %f", pObject->iID, pObject->Velocity.x, pObject->Velocity.y, pObject->Velocity.z ) ); + PhysicsDebugMsg( String( "Object %d: Position %f %f %f", pObject->iID, pObject->Position.x, pObject->Position.y, pObject->Position.z ) ); + PhysicsDebugMsg( String( "Object %d: Delta Pos %f %f %f", pObject->iID, (pObject->OldPosition.x - pObject->Position.x ), (pObject->OldPosition.y - pObject->Position.y ), ( pObject->OldPosition.z - pObject->Position.z ) ) ); + } + +// if ( pObject->Obj.usItem == MORTAR_SHELL && !pObject->fTestObject && pObject->ubActionCode == THROW_ARM_ITEM ) +//DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("physics.cpp line 524, usItemClass=%d",Item[pObject->Obj.usItem].usItemClass)); + if ( Item[pObject->Obj.usItem].usItemClass == IC_BOMB && !pObject->fTestObject && pObject->ubActionCode == THROW_ARM_ITEM ) + { + // Start soud if we have reached our max height + if ( pObject->OldVelocity.z >= 0 && pObject->Velocity.z < 0 ) + { + if ( pObject->iSoundID == NO_SAMPLE ) + { + pObject->iSoundID = PlayJA2Sample( MORTAR_WHISTLE, RATE_11025, HIGHVOLUME, 1, MIDDLEPAN ); + } + } + } + + return( TRUE ); +} + + +BOOLEAN PhysicsHandleCollisions( REAL_OBJECT *pObject, INT32 *piCollisionID, real DeltaTime ) +{ + FLOAT dDeltaX, dDeltaY, dDeltaZ; + + + if ( PhysicsCheckForCollisions( pObject, piCollisionID ) ) + { + + dDeltaX = pObject->Position.x - pObject->OldPosition.x; + dDeltaY = pObject->Position.y - pObject->OldPosition.y; + dDeltaZ = pObject->Position.z - pObject->OldPosition.z; + + if ( dDeltaX <= EPSILONV && dDeltaX >= -EPSILONV && + dDeltaY <= EPSILONV && dDeltaY >= -EPSILONV ) + { + pObject->sConsecutiveZeroVelocityCollisions++; + } + + if ( pObject->sConsecutiveZeroVelocityCollisions > 3 ) + { + // We will continue with our Z velocity + pObject->Velocity.x = 0; + pObject->Velocity.y = 0; + + // Check that we are not colliding with structure z + //if ( *piCollisionID == COLLISION_STRUCTURE_Z || *piCollisionID == COLLISION_ROOF ) + if ( *piCollisionID == COLLISION_STRUCTURE_Z || *piCollisionID == COLLISION_ROOF || *piCollisionID == COLLISION_GROUND ) + { + pObject->Velocity.z = 0; + + // Set us not alive! + pObject->fAlive = FALSE; + } + + *piCollisionID = COLLISION_NONE; + } + else + { + // Set position back to before collision + pObject->Position = VSetEqual( &(pObject->OldPosition) ); + // Set old position! + pObject->OldPosition.x = pObject->Position.y - dDeltaX; + pObject->OldPosition.y = pObject->Position.x - dDeltaY; + pObject->OldPosition.z = pObject->Position.z - dDeltaZ; + + PhysicsResolveCollision( pObject, &(pObject->CollisionVelocity), &(pObject->CollisionNormal), pObject->CollisionElasticity ); + } + + if ( pObject->Position.z < 0 ) + { + pObject->Position.z = 0; + } + //otherwise, continue falling downwards! + + // TO STOP? + + // Check for delta position values + if ( dDeltaZ <= EPSILONP && dDeltaZ >= -EPSILONP && + dDeltaY <= EPSILONP && dDeltaY >= -EPSILONP && + dDeltaX <= EPSILONP && dDeltaX >= -EPSILONP ) + { + //pObject->fAlive = FALSE; + //return( FALSE ); + } + + // Check for repeated collisions... + //if ( pObject->iOldCollisionCode == COLLISION_ROOF || pObject->iOldCollisionCode == COLLISION_GROUND || pObject->iOldCollisionCode == COLLISION_WATER ) + { + // ATE: This is a safeguard + if ( pObject->sConsecutiveCollisions > 30 ) + { + pObject->fAlive = FALSE; + return( FALSE ); + } + } + + + // 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 ); + //} + } + + return( TRUE ); +} + +void PhysicsDeleteObject( REAL_OBJECT *pObject ) +{ + if ( pObject->fAllocated ) + { + if ( pObject->pNode != NULL ) + { + RemoveStructFromLevelNode( pObject->sLevelNodeGridNo, pObject->pNode ); + } + + if ( pObject->pShadow != NULL ) + { + RemoveShadowFromLevelNode( pObject->sLevelNodeGridNo, pObject->pShadow ); + } + + + RemoveObjectSlot( pObject->iID ); + } +} + + +BOOLEAN PhysicsCheckForCollisions( REAL_OBJECT *pObject, INT32 *piCollisionID ) +{ + vector_3 vTemp; + FLOAT dDeltaX, dDeltaY, dDeltaZ, dX, dY, dZ; + INT32 iCollisionCode = COLLISION_NONE; + BOOLEAN fDoCollision = FALSE; + FLOAT dElasity = 1; + UINT16 usStructureID; + FLOAT dNormalX, dNormalY, dNormalZ; + INT16 sGridNo; + + // Checkf for collisions + dX = pObject->Position.x; + dY = pObject->Position.y; + dZ = pObject->Position.z; + + vTemp.x = 0; + vTemp.y = 0; + vTemp.z = 0; + + dDeltaX = dX - pObject->OldPosition.x; + dDeltaY = dY - pObject->OldPosition.y; + dDeltaZ = dZ - pObject->OldPosition.z; + + //Round delta pos to nearest 0.01 + //dDeltaX = (float)( (int)dDeltaX * 100 ) / 100; + //dDeltaY = (float)( (int)dDeltaY * 100 ) / 100; + //dDeltaZ = (float)( (int)dDeltaZ * 100 ) / 100; + + // SKIP FIRST GRIDNO, WE'LL COLLIDE WITH OURSELVES.... + if ( pObject->fTestObject != TEST_OBJECT_NO_COLLISIONS ) + { + iCollisionCode = CheckForCollision( dX, dY, dZ, dDeltaX, dDeltaY, dDeltaZ, (INT16 *)&usStructureID, &dNormalX, &dNormalY, &dNormalZ ); + } + else if ( pObject->fTestObject == TEST_OBJECT_NO_COLLISIONS ) + { + iCollisionCode = COLLISION_NONE; + + // Are we on a downward slope? + if ( dZ < pObject->TestZTarget && dDeltaZ < 0 ) + { + if (pObject->fTestPositionNotSet ) + { + if ( pObject->TestZTarget > 32 ) + { + pObject->fTestPositionNotSet = FALSE; + pObject->TestZTarget = 0; + } + else + { + iCollisionCode = COLLISION_GROUND; + } + } + else + { + iCollisionCode = COLLISION_GROUND; + } + } + } + + + // If a test object and we have collided with something ( should only be ground ( or roof? ) ) + // Or destination? + if ( pObject->fTestObject == TEST_OBJECT_ANY_COLLISION ) + { + if ( iCollisionCode != COLLISION_GROUND && iCollisionCode != COLLISION_ROOF && iCollisionCode != COLLISION_WATER && iCollisionCode != COLLISION_NONE ) + { + pObject->fTestEndedWithCollision = TRUE; + pObject->fAlive = FALSE; + return( FALSE ); + } + } + + if ( pObject->fTestObject == TEST_OBJECT_NOTWALLROOF_COLLISIONS ) + { + // So we don't collide with ourselves..... + if ( iCollisionCode != COLLISION_WATER && iCollisionCode != COLLISION_GROUND && iCollisionCode != COLLISION_NONE && + iCollisionCode != COLLISION_ROOF && iCollisionCode != COLLISION_INTERIOR_ROOF && + iCollisionCode != COLLISION_WALL_SOUTHEAST && iCollisionCode != COLLISION_WALL_SOUTHWEST && + iCollisionCode != COLLISION_WALL_NORTHEAST && iCollisionCode != COLLISION_WALL_NORTHWEST ) + { + if ( pObject->fFirstTimeMoved || pObject->sFirstGridNo == pObject->sGridNo ) + { + iCollisionCode = COLLISION_NONE; + } + + // If we are NOT a wall or window, ignore.... + if ( pObject->uiNumTilesMoved < 4 ) + { + switch( iCollisionCode ) + { + case COLLISION_MERC: + case COLLISION_STRUCTURE: + case COLLISION_STRUCTURE_Z: + + // Set to no collision ( we shot past ) + iCollisionCode = COLLISION_NONE; + break; + } + } + } + + + switch( iCollisionCode ) + { + // End test with any collision NOT a wall, roof... + case COLLISION_STRUCTURE: + case COLLISION_STRUCTURE_Z: + + // OK, if it's mercs... don't stop + if ( usStructureID >= INVALID_STRUCTURE_ID ) + { + pObject->fTestEndedWithCollision = TRUE; + + if ( !pObject->fEndedWithCollisionPositionSet ) + { + pObject->fEndedWithCollisionPositionSet = TRUE; + pObject->EndedWithCollisionPosition = VSetEqual( &(pObject->Position) ); + } + iCollisionCode = COLLISION_NONE; + } + else + { + if ( !pObject->fEndedWithCollisionPositionSet ) + { + pObject->fEndedWithCollisionPositionSet = TRUE; + pObject->EndedWithCollisionPosition = VSetEqual( &(pObject->Position) ); + } + } + break; + + case COLLISION_ROOF: + + if ( !pObject->fEndedWithCollisionPositionSet ) + { + pObject->fEndedWithCollisionPositionSet = TRUE; + pObject->EndedWithCollisionPosition = VSetEqual( &(pObject->Position) ); + } + break; + + case COLLISION_WATER: + case COLLISION_GROUND: + case COLLISION_MERC: + case COLLISION_INTERIOR_ROOF: + case COLLISION_NONE: + case COLLISION_WINDOW_SOUTHEAST: + case COLLISION_WINDOW_SOUTHWEST: + case COLLISION_WINDOW_NORTHEAST: + case COLLISION_WINDOW_NORTHWEST: + + // Here we just keep going.. + break; + + default: + + // THis is for walls, windows, etc + // here, we set test ended with collision, but keep going... + pObject->fTestEndedWithCollision = TRUE; + break; + } + } + + + if ( pObject->fTestObject != TEST_OBJECT_NOTWALLROOF_COLLISIONS ) + { + if ( iCollisionCode != COLLISION_WATER && iCollisionCode != COLLISION_GROUND && iCollisionCode != COLLISION_NONE && + iCollisionCode != COLLISION_ROOF && iCollisionCode != COLLISION_INTERIOR_ROOF && + iCollisionCode != COLLISION_WALL_SOUTHEAST && iCollisionCode != COLLISION_WALL_SOUTHWEST && + iCollisionCode != COLLISION_WALL_NORTHEAST && iCollisionCode != COLLISION_WALL_NORTHWEST ) + { + // So we don't collide with ourselves..... + if ( pObject->fFirstTimeMoved || pObject->sFirstGridNo == pObject->sGridNo ) + { + iCollisionCode = COLLISION_NONE; + } + + // If we are NOT a wall or window, ignore.... + if ( pObject->uiNumTilesMoved < 4 ) + { + switch( iCollisionCode ) + { + case COLLISION_MERC: + case COLLISION_STRUCTURE: + case COLLISION_STRUCTURE_Z: + + // Set to no collision ( we shot past ) + iCollisionCode = COLLISION_NONE; + break; + } + } + + } + } + + *piCollisionID = iCollisionCode; + + + // If We hit the ground + if ( iCollisionCode > COLLISION_NONE ) + { + if ( pObject->iOldCollisionCode == iCollisionCode ) + { + pObject->sConsecutiveCollisions++; + } + else + { + pObject->sConsecutiveCollisions = 1; + } + + if ( iCollisionCode == COLLISION_WINDOW_NORTHWEST || iCollisionCode == COLLISION_WINDOW_NORTHEAST || iCollisionCode == COLLISION_WINDOW_SOUTHWEST || iCollisionCode == COLLISION_WINDOW_SOUTHEAST ) + { + if ( !pObject->fTestObject ) + { + // Break window! + PhysicsDebugMsg( String( "Object %d: Collision Window", pObject->iID ) ); + + sGridNo = MAPROWCOLTOPOS( ( (INT16)pObject->Position.y / CELL_Y_SIZE ), ( (INT16)pObject->Position.x / CELL_X_SIZE ) ); + + ObjectHitWindow( sGridNo, usStructureID, FALSE, TRUE ); + } + *piCollisionID = COLLISION_NONE; + return( FALSE ); + } + + // ATE: IF detonate on impact, stop now! + if ( OBJECT_DETONATE_ON_IMPACT( pObject ) ) + { + pObject->fAlive = FALSE; + return( TRUE ); + } + + if ( iCollisionCode == COLLISION_GROUND ) + { + vTemp.x = 0; + vTemp.y = 0; + vTemp.z = -1; + + pObject->fApplyFriction = TRUE; + //pObject->AppliedMu = (float)(0.54 * TIME_MULTI ); + pObject->AppliedMu = (float)(0.34 * TIME_MULTI ); + + //dElasity = (float)1.5; + dElasity = (float)1.3; + + fDoCollision = TRUE; + + if ( !pObject->fTestObject && !pObject->fHaveHitGround ) + { + PlayJA2Sample( THROW_IMPACT_2, RATE_11025, SoundVolume( MIDVOLUME, pObject->sGridNo ), 1, SoundDir( pObject->sGridNo ) ); + } + + pObject->fHaveHitGround = TRUE; + } + else if ( iCollisionCode == COLLISION_WATER ) + { + ANITILE_PARAMS AniParams; + ANITILE *pNode; + + // Continue going... + pObject->fApplyFriction = TRUE; + pObject->AppliedMu = (float)(1.54 * TIME_MULTI ); + + sGridNo = MAPROWCOLTOPOS( ( (INT16)pObject->Position.y / CELL_Y_SIZE ), ( (INT16)pObject->Position.x / CELL_X_SIZE ) ); + + // Make thing unalive... + pObject->fAlive = FALSE; + + // If first time... + if ( pObject->fVisible ) + { + if ( pObject->fTestObject == NO_TEST_OBJECT ) + { + // Make invisible + pObject->fVisible = FALSE; + + // JA25 CJC Oct 13 1999 - if node pointer is null don't try to set flags inside it! + if( pObject->pNode ) + { + pObject->pNode->uiFlags |= LEVELNODE_HIDDEN; + } + + pObject->fInWater = TRUE; + + // Make ripple + memset( &AniParams, 0, sizeof( ANITILE_PARAMS ) ); + AniParams.sGridNo = sGridNo; + AniParams.ubLevelID = ANI_STRUCT_LEVEL; + AniParams.usTileType = THIRDMISS; + AniParams.usTileIndex = THIRDMISS1; + AniParams.sDelay = 50; + AniParams.sStartFrame = 0; + AniParams.uiFlags = ANITILE_FORWARD; + + + if ( pObject->ubActionCode == THROW_ARM_ITEM ) + { + AniParams.ubKeyFrame1 = 11; + AniParams.uiKeyFrame1Code = ANI_KEYFRAME_CHAIN_WATER_EXPLOSION; + AniParams.uiUserData = pObject->Obj.usItem; + AniParams.ubUserData2 = pObject->ubOwner; + } + + pNode = CreateAnimationTile( &AniParams ); + + // Adjust for absolute positioning + pNode->pLevelNode->uiFlags |= LEVELNODE_USEABSOLUTEPOS; + + pNode->pLevelNode->sRelativeX = (INT16)pObject->Position.x; + pNode->pLevelNode->sRelativeY = (INT16)pObject->Position.y; + pNode->pLevelNode->sRelativeZ = (INT16)CONVERT_HEIGHTUNITS_TO_PIXELS( (INT16)pObject->Position.z ); + } + } + + } + else if ( iCollisionCode == COLLISION_ROOF || iCollisionCode == COLLISION_INTERIOR_ROOF ) + { + vTemp.x = 0; + vTemp.y = 0; + vTemp.z = -1; + + pObject->fApplyFriction = TRUE; + pObject->AppliedMu = (float)(0.54 * TIME_MULTI ); + + dElasity = (float)1.4; + + fDoCollision = TRUE; + + } + //else if ( iCollisionCode == COLLISION_INTERIOR_ROOF ) + //{ + // vTemp.x = 0; + // vTemp.y = 0; + // vTemp.z = 1; + + // pObject->fApplyFriction = TRUE; + // pObject->AppliedMu = (float)(0.54 * TIME_MULTI ); + + // dElasity = (float)1.4; + + // fDoCollision = TRUE; + + //} + else if ( iCollisionCode == COLLISION_STRUCTURE_Z ) + { + if ( CheckForCatcher( pObject, usStructureID ) ) + { + return( FALSE ); + } + + CheckForObjectHittingMerc( pObject, usStructureID ); + + vTemp.x = 0; + vTemp.y = 0; + vTemp.z = -1; + + pObject->fApplyFriction = TRUE; + pObject->AppliedMu = (float)(0.54 * TIME_MULTI ); + + dElasity = (float)1.2; + + fDoCollision = TRUE; + + } + else if ( iCollisionCode == COLLISION_WALL_SOUTHEAST || iCollisionCode == COLLISION_WALL_SOUTHWEST || + iCollisionCode == COLLISION_WALL_NORTHEAST || iCollisionCode == COLLISION_WALL_NORTHWEST ) + { + // A wall, do stuff + vTemp.x = dNormalX; + vTemp.y = dNormalY; + vTemp.z = dNormalZ; + + fDoCollision = TRUE; + + dElasity = (float)1.1; + } + else + { + vector_3 vIncident; + + if ( CheckForCatcher( pObject, usStructureID ) ) + { + return( FALSE ); + } + + CheckForObjectHittingMerc( pObject, usStructureID ); + + vIncident.x = dDeltaX; + vIncident.y = dDeltaY; + vIncident.z = 0; + // Nomralize + + vIncident = VGetNormal( &vIncident ); + + //vTemp.x = -1; + //vTemp.y = 0; + //vTemp.z = 0; + vTemp.x = -1 * vIncident.x; + vTemp.y = -1 * vIncident.y; + vTemp.z = 0; + + fDoCollision = TRUE; + + dElasity = (float)1.1; + } + + if ( fDoCollision ) + { + pObject->CollisionNormal.x = vTemp.x; + pObject->CollisionNormal.y = vTemp.y; + pObject->CollisionNormal.z = vTemp.z; + pObject->CollisionElasticity = dElasity; + pObject->iOldCollisionCode = iCollisionCode; + + // Save collision velocity + pObject->CollisionVelocity = VSetEqual( &(pObject->OldVelocity) ); + + if ( pObject->fPotentialForDebug ) + { + PhysicsDebugMsg( String( "Object %d: Collision %d", pObject->iID, iCollisionCode ) ); + PhysicsDebugMsg( String( "Object %d: Collision Normal %f %f %f", pObject->iID, vTemp.x, vTemp.y, vTemp.z ) ); + PhysicsDebugMsg( String( "Object %d: Collision OldPos %f %f %f", pObject->iID, pObject->Position.x, pObject->Position.y, pObject->Position.z ) ); + PhysicsDebugMsg( String( "Object %d: Collision Velocity %f %f %f", pObject->iID, pObject->CollisionVelocity.x, pObject->CollisionVelocity.y, pObject->CollisionVelocity.z ) ); + } + + pObject->fColliding = TRUE; + + } + else + { + pObject->fColliding = FALSE; + pObject->sConsecutiveCollisions = 0; + pObject->sConsecutiveZeroVelocityCollisions = 0; + pObject->fHaveHitGround = FALSE; + } + } + + return( fDoCollision ); +} + + +void PhysicsResolveCollision( REAL_OBJECT *pObject, vector_3 *pVelocity, vector_3 *pNormal, real CoefficientOfRestitution ) +{ + real ImpulseNumerator, Impulse; + vector_3 vTemp; + + ImpulseNumerator = -1 * CoefficientOfRestitution * VDotProduct( pVelocity , pNormal ); + + Impulse = ImpulseNumerator; + + vTemp = VMultScalar( pNormal, Impulse ); + + pObject->Velocity = VAdd( &(pObject->Velocity), &vTemp ); + +} + +BOOLEAN PhysicsMoveObject( REAL_OBJECT *pObject ) +{ + LEVELNODE *pNode; + INT16 sNewGridNo, sTileIndex; + ETRLEObject *pTrav; + HVOBJECT hVObject; + + + //Determine new gridno + sNewGridNo = MAPROWCOLTOPOS( ( (INT16)pObject->Position.y / CELL_Y_SIZE ), ( (INT16)pObject->Position.x / CELL_X_SIZE ) ); + + if ( pObject->fFirstTimeMoved ) + { + pObject->fFirstTimeMoved = FALSE; + pObject->sFirstGridNo = sNewGridNo; + } + + // CHECK FOR RANGE< IF INVALID, REMOVE! + if ( sNewGridNo == -1 ) + { + PhysicsDeleteObject( pObject ); + return( FALSE ); + } + + // Look at old gridno + if ( sNewGridNo != pObject->sGridNo || pObject->pNode == NULL ) + { + if ( pObject->fVisible ) + { + if ( CheckForCatchObject( pObject ) ) + { + pObject->fVisible = FALSE; + } + } + + if ( pObject->fVisible ) + { + // Add smoke trails... +// if ( pObject->Obj.usItem == MORTAR_SHELL && pObject->uiNumTilesMoved > 2 && pObject->ubActionCode == THROW_ARM_ITEM ) + //DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("physics.cpp line 1147")); + if ( Item[pObject->Obj.usItem].usItemClass == IC_BOMB && pObject->uiNumTilesMoved > 2 && pObject->ubActionCode == THROW_ARM_ITEM ) + { + if ( sNewGridNo != pObject->sGridNo ) + { + ANITILE_PARAMS AniParams; + + AniParams.sGridNo = (INT16)sNewGridNo; + AniParams.ubLevelID = ANI_STRUCT_LEVEL; + AniParams.sDelay = (INT16)( 100 + PreRandom( 100 ) ); + AniParams.sStartFrame = 0; + AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_FORWARD | ANITILE_ALWAYS_TRANSLUCENT; + AniParams.sX = (INT16)pObject->Position.x; + AniParams.sY = (INT16)pObject->Position.y; + AniParams.sZ = (INT16)CONVERT_HEIGHTUNITS_TO_PIXELS( (INT16)pObject->Position.z ); + + strcpy( AniParams.zCachedFile, "TILECACHE\\MSLE_SMK.STI" ); + + CreateAnimationTile( &AniParams ); + } + } + else if ( pObject->uiNumTilesMoved > 0 ) + { + if ( sNewGridNo != pObject->sGridNo ) + { + // We're at a new gridno! + if ( pObject->pNode != NULL ) + { + RemoveStructFromLevelNode( pObject->sLevelNodeGridNo, pObject->pNode ); + } + + // We're at a new gridno! + if ( pObject->pShadow != NULL ) + { + RemoveShadowFromLevelNode( pObject->sLevelNodeGridNo, pObject->pShadow ); + } + + // Now get graphic index + sTileIndex = GetTileGraphicForItem( &(Item[ pObject->Obj.usItem ] ) ); + //sTileIndex = BULLETTILE1; + + // Set new gridno, add + pNode = AddStructToTail( sNewGridNo, sTileIndex ); + pNode->ubShadeLevel=DEFAULT_SHADE_LEVEL; + pNode->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL; + pNode->uiFlags |= ( LEVELNODE_USEABSOLUTEPOS | LEVELNODE_IGNOREHEIGHT | LEVELNODE_PHYSICSOBJECT | LEVELNODE_DYNAMIC ); + + // Set levelnode + pObject->pNode = pNode; + + // Add shadow + AddShadowToHead( sNewGridNo, sTileIndex ); + pNode = gpWorldLevelData[ sNewGridNo ].pShadowHead; + pNode->ubShadeLevel=DEFAULT_SHADE_LEVEL; + pNode->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL; + pNode->uiFlags |= ( LEVELNODE_USEABSOLUTEPOS | LEVELNODE_IGNOREHEIGHT | LEVELNODE_PHYSICSOBJECT | LEVELNODE_DYNAMIC ); + + // Set levelnode + pObject->pShadow = pNode; + + pObject->sLevelNodeGridNo = sNewGridNo; + } + } + } + else + { + // Remove! + if ( pObject->pNode != NULL ) + { + RemoveStructFromLevelNode( pObject->sLevelNodeGridNo, pObject->pNode ); + } + + // We're at a new gridno! + if ( pObject->pShadow != NULL ) + { + RemoveShadowFromLevelNode( pObject->sLevelNodeGridNo, pObject->pShadow ); + } + + pObject->pNode = NULL; + pObject->pShadow = NULL; + } + + if ( sNewGridNo != pObject->sGridNo ) + { + pObject->uiNumTilesMoved++; + } + + pObject->sGridNo = sNewGridNo; + + if ( pObject->fPotentialForDebug ) + { + PhysicsDebugMsg( String( "Object %d: uiNumTilesMoved: %d", pObject->iID, pObject->uiNumTilesMoved ) ); + } + } + + if ( pObject->fVisible ) + { +// if ( pObject->Obj.usItem != MORTAR_SHELL || pObject->ubActionCode != THROW_ARM_ITEM ) + DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("physics.cpp line 1238")); + if ( !(Item[pObject->Obj.usItem].usItemClass == IC_BOMB) || pObject->ubActionCode != THROW_ARM_ITEM ) + { + if ( pObject->pNode != NULL ) + { + // OK, get offsets + hVObject = gTileDatabase[ pObject->pNode->usIndex ].hTileSurface; + pTrav = &(hVObject->pETRLEObject[ gTileDatabase[ pObject->pNode->usIndex ].usRegionIndex ] ); + + // Add new object / update position + // Update position data + pObject->pNode->sRelativeX = (INT16)pObject->Position.x; // + pTrav->sOffsetX; + pObject->pNode->sRelativeY = (INT16)pObject->Position.y; // + pTrav->sOffsetY; + pObject->pNode->sRelativeZ = (INT16)CONVERT_HEIGHTUNITS_TO_PIXELS( (INT16)pObject->Position.z ); + + // Update position data + pObject->pShadow->sRelativeX = (INT16)pObject->Position.x; // + pTrav->sOffsetX; + pObject->pShadow->sRelativeY = (INT16)pObject->Position.y; // + pTrav->sOffsetY; + pObject->pShadow->sRelativeZ = (INT16)gpWorldLevelData[ pObject->sGridNo ].sHeight; + } + } + } + + return( TRUE ); +} + + + +#if 0 +{ + LEVELNODE *pNode; + INT16 sNewGridNo; + + //Determine new gridno + sNewGridNo = MAPROWCOLTOPOS( ( pObject->Position.y / CELL_Y_SIZE ), ( pObject->Position.x / CELL_X_SIZE ) ); + + // Look at old gridno + if ( sNewGridNo != pObject->sGridNo ) + { + // We're at a new gridno! + + // First find levelnode of our object and delete + pNode = gpWorldLevelData[ pObject->sGridNo ].pStructHead; + + // LOOP THORUGH OBJECT LAYER + while( pNode != NULL ) + { + if ( pNode->uiFlags & LEVELNODE_PHYSICSOBJECT ) + { + if ( pNode->iPhysicsObjectID == pObject->iID ) + { + RemoveStruct( pObject->sGridNo, pNode->usIndex ); + break; + } + } + + pNode = ppNode->pNext; + } + + // Set new gridno, add + } + // Add new object / update position + +} +#endif + +void ObjectHitWindow( INT16 sGridNo, UINT16 usStructureID, BOOLEAN fBlowWindowSouth, BOOLEAN fLargeForce ) +{ + EV_S_WINDOWHIT SWindowHit; + SWindowHit.sGridNo = sGridNo; + SWindowHit.usStructureID = usStructureID; + SWindowHit.fBlowWindowSouth = fBlowWindowSouth; + SWindowHit.fLargeForce = fLargeForce; + //AddGameEvent( S_WINDOWHIT, 0, &SWindowHit ); + + WindowHit( sGridNo, usStructureID, fBlowWindowSouth, fLargeForce ); + +} + + +vector_3 FindBestForceForTrajectory( INT16 sSrcGridNo, INT16 sGridNo,INT16 sStartZ, INT16 sEndZ, real dzDegrees, OBJECTTYPE *pItem, INT16 *psGridNo, real *pdMagForce ) +{ + vector_3 vDirNormal, vPosition, vForce; + INT16 sDestX, sDestY, sSrcX, sSrcY; + real dForce = 20; + real dRange; + real dPercentDiff = 0; + real dTestRange, dTestDiff; + INT32 iNumChecks = 0; + + // Get XY from gridno + ConvertGridNoToCenterCellXY( sGridNo, &sDestX, &sDestY ); + ConvertGridNoToCenterCellXY( sSrcGridNo, &sSrcX, &sSrcY ); + + // Set position + vPosition.x = sSrcX; + vPosition.y = sSrcY; + vPosition.z = sStartZ; + + // OK, get direction normal + vDirNormal.x = (float)(sDestX - sSrcX); + vDirNormal.y = (float)(sDestY - sSrcY); + vDirNormal.z = 0; + + // NOmralize + vDirNormal = VGetNormal( &vDirNormal ); + + // From degrees, calculate Z portion of normal + vDirNormal.z = (float)sin( dzDegrees ); + + // Get range + dRange = (float)GetRangeInCellCoordsFromGridNoDiff( sGridNo, sSrcGridNo ); + + //calculate force needed + { + dForce = (float)( 12 * ( sqrt( ( GRAVITY * dRange ) / sin( 2 * dzDegrees ) ) ) ); + } + + do + { + // This first force is just an estimate... + // now di a binary search to find best value.... + iNumChecks++; + + + // Now use a force + vForce.x = dForce * vDirNormal.x; + vForce.y = dForce * vDirNormal.y; + vForce.z = dForce * vDirNormal.z; + + dTestRange = CalculateObjectTrajectory( sEndZ, pItem, &vPosition, &vForce, psGridNo ); + + // What's the diff? + dTestDiff = dTestRange - dRange; + + // How have we done? + // < 5% off... + if ( fabs( ( dTestDiff / dRange ) ) < .01 ) + { + break; + } + + if ( iNumChecks > MAX_INTEGRATIONS ) + { + break; + } + + // What is the Percentage difference? + dPercentDiff = dForce * ( dTestDiff / dRange ); + + // Adjust force accordingly + dForce = dForce - ( ( dPercentDiff ) / 2 ); + + } while( TRUE ); + + // OK, we have our force, calculate change to get through without collide + //if ( ChanceToGetThroughObjectTrajectory( sEndZ, pItem, &vPosition, &vForce, NULL ) == 0 ) + { + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Chance to get through throw is 0." ); + } + + if ( pdMagForce ) + { + (*pdMagForce) = dForce; + } + +#ifdef JA2TESTVERSION + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Number of integration: %d", iNumChecks ); +#endif + + return( vForce ); +} + + +INT16 FindFinalGridNoGivenDirectionGridNoForceAngle( INT16 sSrcGridNo, INT16 sGridNo, INT16 sStartZ, INT16 sEndZ, real dForce, real dzDegrees, OBJECTTYPE *pItem ) +{ + vector_3 vDirNormal, vPosition, vForce; + INT16 sDestX, sDestY, sSrcX, sSrcY; + real dRange; + INT16 sEndGridNo; + + + // Get XY from gridno + ConvertGridNoToCenterCellXY( sGridNo, &sDestX, &sDestY ); + ConvertGridNoToCenterCellXY( sSrcGridNo, &sSrcX, &sSrcY ); + + // Set position + vPosition.x = sSrcX; + vPosition.y = sSrcY; + vPosition.z = sStartZ; + + // OK, get direction normal + vDirNormal.x = (float)(sDestX - sSrcX); + vDirNormal.y = (float)(sDestY - sSrcY); + vDirNormal.z = 0; + + // NOmralize + vDirNormal = VGetNormal( &vDirNormal ); + + // From degrees, calculate Z portion of normal + vDirNormal.z = (float)sin( dzDegrees ); + + // Get range + dRange = (float)GetRangeInCellCoordsFromGridNoDiff( sGridNo, sSrcGridNo ); + + // Now use a force + vForce.x = dForce * vDirNormal.x; + vForce.y = dForce * vDirNormal.y; + vForce.z = dForce * vDirNormal.z; + + CalculateObjectTrajectory( sEndZ, pItem, &vPosition, &vForce, &sEndGridNo ); + + return( sEndGridNo ); +} + + +real FindBestAngleForTrajectory( INT16 sSrcGridNo, INT16 sGridNo,INT16 sStartZ, INT16 sEndZ, real dForce, OBJECTTYPE *pItem, INT16 *psGridNo ) +{ + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"FindBestAngleForTrajectory"); + + vector_3 vDirNormal, vPosition, vForce; + INT16 sDestX, sDestY, sSrcX, sSrcY; + real dRange; + real dzDegrees = ( (float)PI/8 ); + real dPercentDiff = 0; + real dTestRange, dTestDiff; + INT32 iNumChecks = 0; + + + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"FindBestAngleForTrajectory: get range and direction"); + // Get XY from gridno + ConvertGridNoToCenterCellXY( sGridNo, &sDestX, &sDestY ); + ConvertGridNoToCenterCellXY( sSrcGridNo, &sSrcX, &sSrcY ); + + // Set position + vPosition.x = sSrcX; + vPosition.y = sSrcY; + vPosition.z = sStartZ; + + // OK, get direction normal + vDirNormal.x = (float)(sDestX - sSrcX); + vDirNormal.y = (float)(sDestY - sSrcY); + vDirNormal.z = 0; + + // NOmralize + vDirNormal = VGetNormal( &vDirNormal ); + + // From degrees, calculate Z portion of normal + vDirNormal.z = (float)sin( dzDegrees ); + + // Get range + dRange = (float)GetRangeInCellCoordsFromGridNoDiff( sGridNo, sSrcGridNo ); + + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"FindBestAngleForTrajectory: find best direction"); + do + { + // This first direction is just an estimate... + // now do a binary search to find best value.... + iNumChecks++; + + // Now use a force + vForce.x = dForce * vDirNormal.x; + vForce.y = dForce * vDirNormal.y; + vForce.z = dForce * vDirNormal.z; + + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"FindBestAngleForTrajectory: CalculateObjectTrajectory"); + dTestRange = CalculateObjectTrajectory( sEndZ, pItem, &vPosition, &vForce, psGridNo ); + + // What's the diff? + dTestDiff = dTestRange - dRange; + + // How have we done? + // < 5% off... + if ( fabs( (FLOAT)( dTestDiff / dRange ) ) < .05 ) + { + break; + } + + if ( iNumChecks > MAX_INTEGRATIONS ) + { + break; + } + + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"FindBestAngleForTrajectory: get percentage difference"); + // What is the Percentage difference? + dPercentDiff = dzDegrees * ( dTestDiff / dRange ); + + // Adjust degrees accordingly + dzDegrees = dzDegrees - ( dPercentDiff / 2 ); + + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"FindBestAngleForTrajectory: check angle"); + // OK, If our angle is too far either way, giveup! + if ( fabs( dzDegrees ) >= ( PI / 2 ) || fabs( dzDegrees ) <= 0.005 ) + { + // Use 0..... + dzDegrees = 0; + // From degrees, calculate Z portion of normal + vDirNormal.z = (float)sin( dzDegrees ); + // Now use a force + vForce.x = dForce * vDirNormal.x; + vForce.y = dForce * vDirNormal.y; + vForce.z = dForce * vDirNormal.z; + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"FindBestAngleForTrajectory: giving up CalculateObjectTrajectory"); + dTestRange = CalculateObjectTrajectory( sEndZ, pItem, &vPosition, &vForce, psGridNo ); + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"FindBestAngleForTrajectory: giving up returning 0"); + return( (FLOAT)( dzDegrees ) ); + } + + + // From degrees, calculate Z portion of normal + vDirNormal.z = (float)sin( dzDegrees ); + + } while( TRUE ); + + // OK, we have our force, calculate change to get through without collide + //if ( ChanceToGetThroughObjectTrajectory( sEndZ, pItem, &vPosition, &vForce ) == 0 ) + //{ + // ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Chance to get through throw is 0." ); + //} + + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"FindBestAngleForTrajectory done"); + return( dzDegrees ); +} + + +void FindTrajectory( INT16 sSrcGridNo, INT16 sGridNo, INT16 sStartZ, INT16 sEndZ, real dForce, real dzDegrees, OBJECTTYPE *pItem, INT16 *psGridNo ) +{ + vector_3 vDirNormal, vPosition, vForce; + INT16 sDestX, sDestY, sSrcX, sSrcY; + + // Get XY from gridno + ConvertGridNoToCenterCellXY( sGridNo, &sDestX, &sDestY ); + ConvertGridNoToCenterCellXY( sSrcGridNo, &sSrcX, &sSrcY ); + + // Set position + vPosition.x = sSrcX; + vPosition.y = sSrcY; + vPosition.z = sStartZ; + + // OK, get direction normal + vDirNormal.x = (float)(sDestX - sSrcX); + vDirNormal.y = (float)(sDestY - sSrcY); + vDirNormal.z = 0; + + // NOmralize + vDirNormal = VGetNormal( &vDirNormal ); + + // From degrees, calculate Z portion of normal + vDirNormal.z = (float)sin( dzDegrees ); + + // Now use a force + vForce.x = dForce * vDirNormal.x; + vForce.y = dForce * vDirNormal.y; + vForce.z = dForce * vDirNormal.z; + + CalculateObjectTrajectory( sEndZ, pItem, &vPosition, &vForce, psGridNo ); +} + + + +// OK, this will, given a target Z, INVTYPE, source, target gridnos, initial force vector, will +// return range + +FLOAT CalculateObjectTrajectory( INT16 sTargetZ, OBJECTTYPE *pItem, vector_3 *vPosition, vector_3 *vForce, INT16 *psFinalGridNo ) +{ + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateObjectTrajectory"); + INT32 iID; + REAL_OBJECT *pObject; + FLOAT dDiffX, dDiffY; + INT16 sGridNo; + + if ( psFinalGridNo ) + { + (*psFinalGridNo) = NOWHERE; + } + + + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateObjectTrajectory: createphysicalobject"); + // OK, create a physics object.... + iID = CreatePhysicalObject( pItem, -1, vPosition->x, vPosition->y, vPosition->z, vForce->x, vForce->y, vForce->z, NOBODY, NO_THROW_ACTION, 0 ); + + if ( iID == -1 ) + { + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateObjectTrajectory: returning -1"); + return( -1 ); + } + + pObject = &( ObjectSlots[ iID ] ); + + // Set some special values... + pObject->fTestObject = TEST_OBJECT_NO_COLLISIONS; + pObject->TestZTarget = sTargetZ; + pObject->fTestPositionNotSet = TRUE; + pObject->fVisible = FALSE; + + // Alrighty, move this beast until it dies.... + while( pObject->fAlive ) + { + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateObjectTrajectory: calling simulateobject - this object never fucking dies!!!!"); + SimulateObject( pObject, (float)DELTA_T ); + } + + // Calculate gridno from last position + sGridNo = MAPROWCOLTOPOS( ( (INT16)pObject->Position.y / CELL_Y_SIZE ), ( (INT16)pObject->Position.x / CELL_X_SIZE ) ); + + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateObjectTrajectory: physicsdeleteobject"); + PhysicsDeleteObject( pObject ); + + // get new x, y, z values + dDiffX = ( pObject->TestTargetPosition.x - vPosition->x ); + dDiffY = ( pObject->TestTargetPosition.y - vPosition->y ); + + if ( psFinalGridNo ) + { + (*psFinalGridNo) = sGridNo; + } + + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateObjectTrajectory: done"); + return( (FLOAT)sqrt( ( dDiffX * dDiffX ) + ( dDiffY * dDiffY ) ) ); + +} + + +INT32 ChanceToGetThroughObjectTrajectory( INT16 sTargetZ, OBJECTTYPE *pItem, vector_3 *vPosition, vector_3 *vForce, INT16 *psNewGridNo, INT8 *pbLevel, BOOLEAN fFromUI ) +{ + INT32 iID; + REAL_OBJECT *pObject; + + // OK, create a physics object.... + iID = CreatePhysicalObject( pItem, -1, vPosition->x, vPosition->y, vPosition->z, vForce->x, vForce->y, vForce->z, NOBODY, NO_THROW_ACTION, 0 ); + + if ( iID == -1 ) + { + return( -1 ); + } + + pObject = &( ObjectSlots[ iID ] ); + + // Set some special values... + pObject->fTestObject = TEST_OBJECT_NOTWALLROOF_COLLISIONS; + pObject->fTestPositionNotSet = TRUE; + pObject->TestZTarget = sTargetZ; + pObject->fVisible = FALSE; + //pObject->fPotentialForDebug = TRUE; + + // Alrighty, move this beast until it dies.... + while( pObject->fAlive ) + { + SimulateObject( pObject, (float)DELTA_T ); + } + + + if ( psNewGridNo != NULL ) + { + // Calculate gridno from last position + + // If NOT from UI, use exact collision position + // JA25 comment from CJC: testing breaklights, we ran into a situation where EndedWithCollisionPosition was not + // set due to breaklight stopping on flat ground. It makes sense that if EndedWithCollisionPosition is + // unset, at least the Position value is of SOME use... + if ( fFromUI || (pObject->EndedWithCollisionPosition.x == 0.0f && pObject->EndedWithCollisionPosition.y == 0.0f) ) + { + (*psNewGridNo) = MAPROWCOLTOPOS( ( (INT16)pObject->Position.y / CELL_Y_SIZE ), ( (INT16)pObject->Position.x / CELL_X_SIZE ) ); + } + else + { + (*psNewGridNo) = MAPROWCOLTOPOS( ( (INT16)pObject->EndedWithCollisionPosition.y / CELL_Y_SIZE ), ( (INT16)pObject->EndedWithCollisionPosition.x / CELL_X_SIZE ) ); + } + + (*pbLevel) = GET_OBJECT_LEVEL( pObject->EndedWithCollisionPosition.z - CONVERT_PIXELS_TO_HEIGHTUNITS( gpWorldLevelData[ (*psNewGridNo) ].sHeight ) ); + } + + PhysicsDeleteObject( pObject ); + + // See If we collided + if ( pObject->fTestEndedWithCollision ) + { + return( 0 ); + } + return( 100 ); + +} + + + + +FLOAT CalculateLaunchItemAngle( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubHeight, real dForce, OBJECTTYPE *pItem, INT16 *psGridNo ) +{ + real dAngle; + INT16 sSrcX, sSrcY; + + ConvertGridNoToCenterCellXY( pSoldier->sGridNo, &sSrcX, &sSrcY ); + + dAngle = FindBestAngleForTrajectory( pSoldier->sGridNo, sGridNo, GET_SOLDIER_THROW_HEIGHT( pSoldier->bLevel ), ubHeight, dForce, pItem, psGridNo ); + + // new we have defaut angle value... + return( dAngle ); +} + + + +void CalculateLaunchItemBasicParams( SOLDIERTYPE *pSoldier, OBJECTTYPE *pItem, INT16 sGridNo, UINT8 ubLevel, INT16 sEndZ, FLOAT *pdMagForce, FLOAT *pdDegrees, INT16 *psFinalGridNo, BOOLEAN fArmed ) +{ + INT16 sInterGridNo; + INT16 sStartZ; + FLOAT dMagForce, dMaxForce, dMinForce; + FLOAT dDegrees, dNewDegrees; + BOOLEAN fThroughIntermediateGridNo = FALSE; + UINT16 usLauncher; + BOOLEAN fIndoors = FALSE; + BOOLEAN fLauncher = FALSE; + BOOLEAN fMortar = FALSE; + BOOLEAN fGLauncher = FALSE; + INT16 sMinRange = 0; + + // Start with default degrees/ force + dDegrees = OUTDOORS_START_ANGLE; + sStartZ = GET_SOLDIER_THROW_HEIGHT( pSoldier->bLevel ); + + // Are we armed, and are we throwing a LAUNCHABLE? + + usLauncher = GetLauncherFromLaunchable( pItem->usItem ); +DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("physics.cpp line 1741")); + if ( fArmed && ( Item[usLauncher].mortar || Item[pItem->usItem].mortar ) ) + { + // Start at 0.... + sStartZ = ( pSoldier->bLevel * 256 ); + fMortar = TRUE; + sMinRange = MIN_MORTAR_RANGE; + //fLauncher = TRUE; + } +DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("physics.cpp line 1750")); + + if ( fArmed && ( Item[usLauncher].grenadelauncher || Item[pItem->usItem].grenadelauncher ) ) + { + // OK, look at target level and decide angle to use... + if ( ubLevel == 1 ) + { + //dDegrees = GLAUNCHER_START_ANGLE; + dDegrees = GLAUNCHER_HIGHER_LEVEL_START_ANGLE; + } + else + { + dDegrees = GLAUNCHER_START_ANGLE; + } + fGLauncher = TRUE; + sMinRange = MIN_MORTAR_RANGE; + //fLauncher = TRUE; + } + + // CHANGE DEGREE VALUES BASED ON IF WE ARE INSIDE, ETC + // ARE WE INSIDE? + + if ( gfCaves || gfBasement ) + { + // Adjust angle.... + dDegrees = INDOORS_START_ANGLE; + fIndoors = TRUE; + } + + if ( ( IsRoofPresentAtGridno( pSoldier->sGridNo ) ) && pSoldier->bLevel == 0 ) + { + // Adjust angle.... + dDegrees = INDOORS_START_ANGLE; + fIndoors = TRUE; + } + + // IS OUR TARGET INSIDE? + if ( IsRoofPresentAtGridno( sGridNo ) && ubLevel == 0 ) + { + // Adjust angle.... + dDegrees = INDOORS_START_ANGLE; + fIndoors = TRUE; + } + + + // OK, look if we can go through a windows here... + if ( ubLevel == 0 ) + { + sInterGridNo = SoldierToLocationWindowTest( pSoldier, sGridNo ); + } + else + { + sInterGridNo = NOWHERE; + } + + if ( sInterGridNo != NOWHERE ) + { + // IF so, adjust target height, gridno.... + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Through a window!" ); + + fThroughIntermediateGridNo = TRUE; + } + + if ( !fLauncher ) + { + // Find force for basic + FindBestForceForTrajectory( pSoldier->sGridNo, sGridNo, sStartZ, sEndZ, dDegrees, pItem, psFinalGridNo, &dMagForce ); + + // Adjust due to max range.... + dMaxForce = CalculateSoldierMaxForce( pSoldier, dDegrees, pItem, fArmed ); + + if ( fIndoors ) + { + dMaxForce = dMaxForce * 2; + } + + if ( dMagForce > dMaxForce ) + { + dMagForce = dMaxForce; + } + + // ATE: If we are a mortar, make sure we are at min. + if ( fMortar || fGLauncher ) + { + // find min force + dMinForce = CalculateForceFromRange( (INT16)( sMinRange / 10 ), (FLOAT)( PI / 4 ) ); + + if ( dMagForce < dMinForce ) + { + dMagForce = dMinForce; + } + } + + if ( fThroughIntermediateGridNo ) + { + // Given this power, now try and go through this window.... + dDegrees = FindBestAngleForTrajectory( pSoldier->sGridNo, sInterGridNo, GET_SOLDIER_THROW_HEIGHT( pSoldier->bLevel ), 150, dMagForce, pItem, psFinalGridNo ); + } + } + else + { + // Use MAX force, vary angle.... + dMagForce = CalculateSoldierMaxForce( pSoldier, dDegrees, pItem, fArmed ); + + if ( ubLevel == 0 ) + { + dMagForce = (float)( dMagForce * 1.25 ); + } + + FindTrajectory( pSoldier->sGridNo, sGridNo, sStartZ, sEndZ, dMagForce, dDegrees, pItem, psFinalGridNo ); + + if ( ubLevel == 1 && !fThroughIntermediateGridNo ) + { + // Is there a guy here...? + if ( WhoIsThere2( sGridNo, ubLevel ) != NO_SOLDIER ) + { + dMagForce = (float)( dMagForce * 0.85 ); + + // Yep, try to get angle... + dNewDegrees = FindBestAngleForTrajectory( pSoldier->sGridNo, sGridNo, GET_SOLDIER_THROW_HEIGHT( pSoldier->bLevel ), 150, dMagForce, pItem, psFinalGridNo ); + + if ( dNewDegrees != 0 ) + { + dDegrees = dNewDegrees; + } + } + } + + if ( fThroughIntermediateGridNo ) + { + dDegrees = FindBestAngleForTrajectory( pSoldier->sGridNo, sInterGridNo, GET_SOLDIER_THROW_HEIGHT( pSoldier->bLevel ), 150, dMagForce, pItem, psFinalGridNo ); + } + } + + + (*pdMagForce) = dMagForce; + (*pdDegrees ) = dDegrees; +} + + +BOOLEAN CalculateLaunchItemChanceToGetThrough( SOLDIERTYPE *pSoldier, OBJECTTYPE *pItem, INT16 sGridNo, UINT8 ubLevel, INT16 sEndZ, INT16 *psFinalGridNo, BOOLEAN fArmed, INT8 *pbLevel, BOOLEAN fFromUI ) +{ + FLOAT dForce, dDegrees; + INT16 sDestX, sDestY, sSrcX, sSrcY; + vector_3 vForce, vPosition, vDirNormal; + + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateLaunchItemChanceToGetThrough"); + // Ge7t basic launch params... + CalculateLaunchItemBasicParams( pSoldier, pItem, sGridNo, ubLevel, sEndZ, &dForce, &dDegrees, psFinalGridNo, fArmed ); + + // Get XY from gridno + ConvertGridNoToCenterCellXY( sGridNo, &sDestX, &sDestY ); + ConvertGridNoToCenterCellXY( pSoldier->sGridNo, &sSrcX, &sSrcY ); + + // Set position + vPosition.x = sSrcX; + vPosition.y = sSrcY; + vPosition.z = GET_SOLDIER_THROW_HEIGHT( pSoldier->bLevel ); + + // OK, get direction normal + vDirNormal.x = (float)(sDestX - sSrcX); + vDirNormal.y = (float)(sDestY - sSrcY); + vDirNormal.z = 0; + + // NOmralize + vDirNormal = VGetNormal( &vDirNormal ); + + // From degrees, calculate Z portion of normal + vDirNormal.z = (float)sin( dDegrees ); + + // Do force.... + vForce.x = dForce * vDirNormal.x; + vForce.y = dForce * vDirNormal.y; + vForce.z = dForce * vDirNormal.z; + + // OK, we have our force, calculate change to get through without collide + if ( ChanceToGetThroughObjectTrajectory( sEndZ, pItem, &vPosition, &vForce, psFinalGridNo, pbLevel, fFromUI ) == 0 ) + { + return( FALSE ); + } + + if ( (*pbLevel) != ubLevel ) + { + return( FALSE ); + } + + if ( !fFromUI && (*psFinalGridNo) != sGridNo ) + { + return( FALSE ); + } + + return( TRUE ); +} + + + +FLOAT CalculateForceFromRange( INT16 sRange, FLOAT dDegrees ) +{ + FLOAT dMagForce; + INT16 sSrcGridNo, sDestGridNo; + OBJECTTYPE Object; + INT16 sFinalGridNo; + + // OK, use a fake gridno, find the new gridno based on range, use height of merc, end height of ground, + // 45 degrees + sSrcGridNo = 4408; + sDestGridNo = 4408 + ( sRange * WORLD_COLS ); + + // Use a grenade objecttype + CreateItem( HAND_GRENADE, 100, &Object ); + + FindBestForceForTrajectory( sSrcGridNo, sDestGridNo, GET_SOLDIER_THROW_HEIGHT( 0 ), 0, dDegrees, &Object, &sFinalGridNo, &dMagForce ); + + return( dMagForce ); +} + + +FLOAT CalculateSoldierMaxForce( SOLDIERTYPE *pSoldier, FLOAT dDegrees , OBJECTTYPE *pItem , BOOLEAN fArmed ) +{ + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateSoldierMaxForce"); + + INT32 uiMaxRange; + FLOAT dMagForce; + + dDegrees = (FLOAT)( PI/4 ); + + uiMaxRange = CalcMaxTossRange( pSoldier, pItem->usItem, fArmed ); + + dMagForce = CalculateForceFromRange( (INT16) uiMaxRange, dDegrees ); + + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateSoldierMaxForce: done"); + return( dMagForce ); +} + + +#define MAX_MISS_BY 30 +#define MIN_MISS_BY 1 +#define MAX_MISS_RADIUS 5 + +void CalculateLaunchItemParamsForThrow( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubLevel, INT16 sEndZ, OBJECTTYPE *pItem, INT8 bMissBy, UINT8 ubActionCode, UINT32 uiActionData ) +{ + FLOAT dForce, dDegrees; + INT16 sDestX, sDestY, sSrcX, sSrcY; + vector_3 vForce, vDirNormal; + INT16 sFinalGridNo; + BOOLEAN fArmed = FALSE; + UINT16 usLauncher; + INT16 sStartZ; + INT8 bMinMissRadius, bMaxMissRadius, bMaxRadius; + FLOAT fScale; + + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateLaunchItemParamsForThrow"); + + // Set target ID if anyone + pSoldier->ubTargetID = WhoIsThere2( sGridNo, ubLevel ); + + if ( ubActionCode == THROW_ARM_ITEM ) + { + fArmed = TRUE; + } + + if ( bMissBy < 0 ) + { + // then we hit! + bMissBy = 0; + } + + //if ( 0 ) + if ( bMissBy > 0 ) + { + // Max the miss variance + if ( bMissBy > MAX_MISS_BY ) + { + bMissBy = MAX_MISS_BY; + } + + // Min the miss varience... + if ( bMissBy < MIN_MISS_BY ) + { + bMissBy = MIN_MISS_BY; + } + + // Adjust position, force, angle +#ifdef JA2TESTVERSION + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Throw miss by: %d", bMissBy ); +#endif + + // Default to max radius... + bMaxRadius = 5; + + // scale if pyth spaces away is too far + if ( PythSpacesAway( sGridNo, pSoldier->sGridNo ) < ( (float)bMaxRadius / (float)1.5 ) ) + { + bMaxRadius = PythSpacesAway( sGridNo, pSoldier->sGridNo ) / 2; + } + + + // Get radius + fScale = ( (float)bMissBy / (float) MAX_MISS_BY ); + + bMaxMissRadius = (INT8)( bMaxRadius * fScale ); + + // Limit max radius... + if ( bMaxMissRadius > 4 ) + { + bMaxMissRadius = 4; + } + + + bMinMissRadius = bMaxMissRadius - 1; + + if ( bMinMissRadius < 2 ) + { + bMinMissRadius = 2; + } + + if ( bMaxMissRadius < bMinMissRadius ) + { + bMaxMissRadius = bMinMissRadius; + } + + sGridNo = RandomGridFromRadius( sGridNo, bMinMissRadius, bMaxMissRadius ); + } + + // Get basic launch params... + CalculateLaunchItemBasicParams( pSoldier, pItem, sGridNo, ubLevel, sEndZ, &dForce, &dDegrees, &sFinalGridNo, fArmed ); + + // Get XY from gridno + ConvertGridNoToCenterCellXY( sGridNo, &sDestX, &sDestY ); + ConvertGridNoToCenterCellXY( pSoldier->sGridNo, &sSrcX, &sSrcY ); + + // OK, get direction normal + vDirNormal.x = (float)(sDestX - sSrcX); + vDirNormal.y = (float)(sDestY - sSrcY); + vDirNormal.z = 0; + + // NOmralize + vDirNormal = VGetNormal( &vDirNormal ); + + // From degrees, calculate Z portion of normal + vDirNormal.z = (float)sin( dDegrees ); + + // Do force.... + vForce.x = dForce * vDirNormal.x; + vForce.y = dForce * vDirNormal.y; + vForce.z = dForce * vDirNormal.z; + + + // Allocate Throw Parameters + pSoldier->pThrowParams = (THROW_PARAMS *) MemAlloc( sizeof( THROW_PARAMS ) ); + memset( pSoldier->pThrowParams, 0, sizeof( THROW_PARAMS ) ); + + pSoldier->pTempObject = (OBJECTTYPE *) MemAlloc( sizeof( OBJECTTYPE ) ); + + memcpy( pSoldier->pTempObject, pItem, sizeof( OBJECTTYPE ) ); + pSoldier->pThrowParams->dX = (float)sSrcX; + pSoldier->pThrowParams->dY = (float)sSrcY; + + + sStartZ = GET_SOLDIER_THROW_HEIGHT( pSoldier->bLevel ); + usLauncher = GetLauncherFromLaunchable( pItem->usItem ); +DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("physics.cpp line 2103")); + if ( fArmed && Item[usLauncher].mortar ) + { + // Start at 0.... + sStartZ = ( pSoldier->bLevel * 256 ) + 50; + } + + pSoldier->pThrowParams->dZ = (float)sStartZ; + pSoldier->pThrowParams->dForceX = vForce.x; + pSoldier->pThrowParams->dForceY = vForce.y; + pSoldier->pThrowParams->dForceZ = vForce.z; + pSoldier->pThrowParams->dLifeSpan = -1; + pSoldier->pThrowParams->ubActionCode = ubActionCode; + pSoldier->pThrowParams->uiActionData = uiActionData; + + // Dirty interface + DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 ); + + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalculateLaunchItemParamsForThrow done"); +} + + +BOOLEAN CheckForCatcher( REAL_OBJECT *pObject, UINT16 usStructureID ) +{ + // Do we want to catch? + if ( pObject->fTestObject == NO_TEST_OBJECT ) + { + if ( pObject->ubActionCode == THROW_TARGET_MERC_CATCH ) + { + // Is it a guy? + if ( usStructureID < INVALID_STRUCTURE_ID ) + { + //Is it the same guy? + if ( usStructureID == pObject->uiActionData ) + { + if ( DoCatchObject( pObject ) ) + { + pObject->fAlive = FALSE; + return( TRUE ); + } + } + } + } + } + return( FALSE ); +} + + +void CheckForObjectHittingMerc( REAL_OBJECT *pObject, UINT16 usStructureID ) +{ + SOLDIERTYPE *pSoldier; + INT16 sDamage, sBreath; + + // Do we want to catch? + if ( pObject->fTestObject == NO_TEST_OBJECT ) + { + // Is it a guy? + if ( usStructureID < INVALID_STRUCTURE_ID ) + { + if ( pObject->ubLastTargetTakenDamage != (UINT8)usStructureID ) + { + pSoldier = MercPtrs[ usStructureID ]; + + sDamage = 1; + sBreath = 0; + + EVENT_SoldierGotHit( pSoldier, NOTHING, sDamage, sBreath, pSoldier->bDirection, 0, pObject->ubOwner, FIRE_WEAPON_TOSSED_OBJECT_SPECIAL, 0, 0, NOWHERE ); + + pObject->ubLastTargetTakenDamage = (UINT8)( usStructureID ); + } + } + } +} + + +BOOLEAN CheckForCatchObject( REAL_OBJECT *pObject ) +{ + SOLDIERTYPE *pSoldier; + UINT32 uiSpacesAway; + + // Do we want to catch? + if ( pObject->fTestObject == NO_TEST_OBJECT ) + { + if ( pObject->ubActionCode == THROW_TARGET_MERC_CATCH ) + { + pSoldier = MercPtrs[ pObject->uiActionData ]; + + // Is it a guy? + // Are we close to this guy? + uiSpacesAway = PythSpacesAway( pObject->sGridNo, pSoldier->sGridNo ); + + if ( uiSpacesAway < 4 && !pObject->fAttemptedCatch ) + { + if ( pSoldier->usAnimState != CATCH_STANDING && + pSoldier->usAnimState != CATCH_CROUCHED && + pSoldier->usAnimState != LOWER_RIFLE ) + { + if ( gAnimControl[ pSoldier->usAnimState ].ubHeight == ANIM_STAND ) + { + EVENT_InitNewSoldierAnim( pSoldier, CATCH_STANDING, 0 , FALSE ); + } + else if ( gAnimControl[ pSoldier->usAnimState ].ubHeight == ANIM_CROUCH ) + { + EVENT_InitNewSoldierAnim( pSoldier, CATCH_CROUCHED, 0 , FALSE ); + } + + pObject->fCatchAnimOn = TRUE; + } + } + + pObject->fAttemptedCatch = TRUE; + + if ( uiSpacesAway <= 1 && !pObject->fCatchCheckDone ) + { + if ( AttemptToCatchObject( pObject ) ) + { + return( TRUE ); + } + } + } + } + return( FALSE ); +} + + + + +BOOLEAN AttemptToCatchObject( REAL_OBJECT *pObject ) +{ + SOLDIERTYPE *pSoldier; + UINT8 ubChanceToCatch; + + // Get intended target + pSoldier = MercPtrs[ pObject->uiActionData ]; + + // OK, get chance to catch + // base it on...? CC? Dexterity? + ubChanceToCatch = 50 + EffectiveDexterity( pSoldier ) / 2; + +#ifdef JA2TESTVERSION + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Chance To Catch: %d", ubChanceToCatch ); +#endif + + pObject->fCatchCheckDone = TRUE; + + if ( PreRandom( 100 ) > ubChanceToCatch ) + { + return( FALSE ); + } + + pObject->fCatchGood = TRUE; + + return( TRUE ); +} + + +BOOLEAN DoCatchObject( REAL_OBJECT *pObject ) +{ + SOLDIERTYPE *pSoldier; + BOOLEAN fGoodCatch = FALSE; + UINT16 usItem; + + // Get intended target + pSoldier = MercPtrs[ pObject->uiActionData ]; + + // Catch anim..... + switch( gAnimControl[ pSoldier->usAnimState ].ubHeight ) + { + case ANIM_STAND: + + pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; + EVENT_InitNewSoldierAnim( pSoldier, END_CATCH, 0 , FALSE ); + break; + + case ANIM_CROUCH: + + pSoldier->usPendingAnimation = NO_PENDING_ANIMATION; + EVENT_InitNewSoldierAnim( pSoldier, END_CROUCH_CATCH, 0 , FALSE ); + break; + } + + PlayJA2Sample( CATCH_OBJECT, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) ); + + pObject->fCatchAnimOn = FALSE; + + if ( !pObject->fCatchGood ) + { + return( FALSE ); + } + + // Get item + usItem = pObject->Obj.usItem; + + // Transfer object + fGoodCatch = AutoPlaceObject( pSoldier, &(pObject->Obj), TRUE ); + + // Report success.... + if ( fGoodCatch ) + { + pObject->fDropItem = FALSE; + + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pMessageStrings[ MSG_MERC_CAUGHT_ITEM ], pSoldier->name, ShortItemNames[ usItem ] ); + } + + return( TRUE ); +} + + +//#define TESTDUDEXPLOSIVES + +void HandleArmedObjectImpact( REAL_OBJECT *pObject ) +{ + INT16 sZ; + BOOLEAN fDoImpact = FALSE; + BOOLEAN fCheckForDuds = FALSE; + OBJECTTYPE *pObj; + INT32 iTrapped = 0; + UINT16 usFlags = 0; + INT8 bLevel = 0; + + // Calculate pixel position of z + sZ = (INT16)CONVERT_HEIGHTUNITS_TO_PIXELS( (INT16)( pObject->Position.z ) ) - gpWorldLevelData[ pObject->sGridNo ].sHeight; + + // get OBJECTTYPE + pObj = &(pObject->Obj); + + // ATE: Make sure number of objects is 1... + pObj->ubNumberOfObjects = 1; + + if ( Item[ pObj->usItem ].usItemClass & IC_GRENADE ) + { + fCheckForDuds = TRUE; + } + +// if ( pObj->usItem == MORTAR_SHELL ) +DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("physics.cpp line 2337")); + if (Item[ pObj->usItem ].usItemClass == IC_BOMB) + { + fCheckForDuds = TRUE; + } + + if ( Item[ pObj->usItem ].usItemClass & IC_THROWN ) + { + AddItemToPool( pObject->sGridNo, pObj, INVISIBLE, bLevel, usFlags, 0 ); + } + + if ( fCheckForDuds ) + { + // If we landed on anything other than the floor, always! go off... + #ifdef TESTDUDEXPLOSIVES + if ( sZ != 0 || pObject->fInWater ) + #else + if ( sZ != 0 || pObject->fInWater || ( pObj->bStatus[0] >= USABLE && ( PreRandom( 100 ) < (UINT32) pObj->bStatus[0] + PreRandom( 50 ) ) ) ) + #endif + { + fDoImpact = TRUE; + } + else // didn't go off! + { + #ifdef TESTDUDEXPLOSIVES + if ( 1 ) + #else + if ( pObj->bStatus[0] >= USABLE && PreRandom(100) < (UINT32) pObj->bStatus[0] + PreRandom( 50 ) ) + #endif + { + iTrapped = PreRandom( 4 ) + 2; + } + + if ( iTrapped ) + { + // Start timed bomb... + usFlags |= WORLD_ITEM_ARMED_BOMB; + + pObj->bDetonatorType = BOMB_TIMED; + pObj->bDelay = (INT8)( 1 + PreRandom( 2 ) ); + } + + // ATE: If we have collided with roof last... + if ( pObject->iOldCollisionCode == COLLISION_ROOF ) + { + bLevel = 1; + } + + // Add item to pool.... + AddItemToPool( pObject->sGridNo, pObj, INVISIBLE, bLevel, usFlags, 0 ); + + // All teams lok for this... + NotifySoldiersToLookforItems( ); + + if ( pObject->ubOwner != NOBODY ) + { + DoMercBattleSound( MercPtrs[ pObject->ubOwner ], (INT8)( BATTLE_SOUND_CURSE1 ) ); + } + } + } + else + { + fDoImpact = TRUE; + } + + if ( fDoImpact ) + { +DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("physics.cpp line 2403")); + if ( Item[pObject->Obj.usItem].flare ) + { + //if the light object will ber created OFF the ground + if( pObject->Position.z > 0 ) + { + //we cannot create the light source above the ground, or on a roof. The system doesnt support it. + AddItemToPool( pObject->sGridNo, &( pObject->Obj ), 1, 1, 0, -1 ); + } + else + { + // Add a light effect... + NewLightEffect( pObject->sGridNo, LIGHT_FLARE_MARK_1 ); + } + } + else if ( Item[ pObject->Obj.usItem ].usItemClass & IC_GRENADE ) + { +/* ARM: Removed. Rewards even missed throws, and pulling a pin doesn't really teach anything about explosives + if ( MercPtrs[ pObject->ubOwner ]->bTeam == gbPlayerNum && gTacticalStatus.uiFlags & INCOMBAT ) + { + // tossed grenade, not a dud, so grant xp + // EXPLOSIVES GAIN (10): Tossing grenade + if ( pObject->ubOwner != NOBODY ) + { + StatChange( MercPtrs[ pObject->ubOwner ], EXPLODEAMT, 10, FALSE ); + } + } +*/ + + IgniteExplosion( pObject->ubOwner, (INT16)pObject->Position.x, (INT16)pObject->Position.y, sZ, pObject->sGridNo, pObject->Obj.usItem, GET_OBJECT_LEVEL( pObject->Position.z - CONVERT_PIXELS_TO_HEIGHTUNITS( gpWorldLevelData[ pObject->sGridNo ].sHeight ) ) ); + } + else if ( Item[ pObject->Obj.usItem ].usItemClass == IC_BOMB ) //if ( pObject->Obj.usItem == MORTAR_SHELL ) + { + sZ = (INT16)CONVERT_HEIGHTUNITS_TO_PIXELS( (INT16)pObject->Position.z ); + + IgniteExplosion( pObject->ubOwner, (INT16)pObject->Position.x, (INT16)pObject->Position.y, sZ, pObject->sGridNo, pObject->Obj.usItem, GET_OBJECT_LEVEL( pObject->Position.z - CONVERT_PIXELS_TO_HEIGHTUNITS( gpWorldLevelData[ pObject->sGridNo ].sHeight ) ) ); + } + } + +} + + + +BOOLEAN SavePhysicsTableToSaveGameFile( HWFILE hFile ) +{ + UINT32 uiNumBytesWritten=0; + UINT16 usCnt=0; + UINT32 usPhysicsCount=0; + + for( usCnt=0; usCnt=0 && sGridNo < WORLD_MAX && + sGridNo >= leftmost && sGridNo < ( leftmost + WORLD_COLS ) ) + { + fFound = TRUE; + } + + cnt++; + + if ( cnt > 50 ) + { + return( NOWHERE ); + } + + } while( !fFound ); + + return( sGridNo ); +} diff --git a/Utils/PopUpBox.cpp b/Utils/PopUpBox.cpp index f14b973c..61bb0383 100644 --- a/Utils/PopUpBox.cpp +++ b/Utils/PopUpBox.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Utils All.h" #else @@ -1314,8 +1315,8 @@ BOOLEAN DrawBox(UINT32 uiCounter) } // make sure it will fit on screen! - Assert( usTopX + usWidth <= 639 ); - Assert( usTopY + usHeight <= 479 ); + Assert( usTopX + usWidth <= SCREEN_WIDTH ); + Assert( usTopY + usHeight <= SCREEN_HEIGHT ); // subtract 4 because the 2 2-pixel corners are handled separately uiNumTilesWide=((usWidth-4)/BORDER_WIDTH); diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index a6ba7acf..911658e4 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Utils All.h" #else @@ -1904,7 +1905,7 @@ STR16 pMapErrorString[] = L"needs an escort to move. Place her on a squad with one.", // for a female L"Merc hasn't yet arrived in Arulco!", L"Looks like there's some contract negotiations to settle first.", - L"", + L"Cannot give a movement order. Air raid is going on.", // WANNE 2 //11-15 L"Movement orders? There's a battle going on!", L"You have been ambushed by bloodcats in sector %s!", @@ -3300,6 +3301,8 @@ STR16 zMarksMapScreenText[] = L"%s is full of militia.", L"Merc has a finite contract.", L"Merc's contract is not insured", + // WANNE 2 + L"Map Overview", // 24 }; diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 8d589a60..e2de6f95 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -1,3 +1,4 @@ +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Utils All.h" #else @@ -1830,7 +1831,7 @@ STR16 pMapErrorString[] = L"braucht eine Eskorte. Plazieren Sie sie in einem Trupp mit Eskorte.", // for a female L"Söldner ist noch nicht in Arulco!", L"Erst mal Vertrag aushandeln!", - L"", + L"Marschbefehl ist nicht möglich. Luftangriffe finden statt.", // WANNE 2 //11-15 L"Marschbefehl? Hier tobt ein Kampf!", L"Sie sind von Bloodcats umstellt in Sektor %s!", @@ -3108,6 +3109,8 @@ STR16 zMarksMapScreenText[] = L"%s ist voller Milizen.", L"Söldner hat begrenzten Vertrag.", L"Vertrag des Söldners ist nicht versichert", + // WANNE 2 + L"Kartenübersicht", // 24 }; STR16 pLandMarkInSectorString[] = diff --git a/Utils/message.cpp b/Utils/message.cpp index 11680ddd..3ba15fff 100644 --- a/Utils/message.cpp +++ b/Utils/message.cpp @@ -1,4 +1,4 @@ -// WANNE <08.12.2005> +// WANNE 2 #ifdef PRECOMPILEDHEADERS #include "Utils All.h" #include "Game Clock.h" @@ -1086,8 +1086,10 @@ void DisplayStringsInMapScreenMessageList( void ) UINT16 usSpacing; - // WANNE - SetFontDestBuffer( FRAME_BUFFER, 17, 360 + 6, 407, 360 + 101, FALSE ); + // WANNE 2 + //SetFontDestBuffer( FRAME_BUFFER, 17, 360 + 6, 407, 360 + 101, FALSE ); + + SetFontDestBuffer( FRAME_BUFFER, 17, (SCREEN_HEIGHT - 114), 407, (SCREEN_HEIGHT - 114) + 101, FALSE ); SetFont( MAP_SCREEN_MESSAGE_FONT ); // no longer supports variable fonts SetFontBackground( FONT_BLACK ); @@ -1095,7 +1097,10 @@ void DisplayStringsInMapScreenMessageList( void ) ubCurrentStringIndex = gubCurrentMapMessageString; - sY = 377; + // WANNE 2 + //sY = 377; + sY = (SCREEN_HEIGHT - 103); + usSpacing = GetFontHeight( MAP_SCREEN_MESSAGE_FONT ); for ( ubLinesPrinted = 0; ubLinesPrinted < MAX_MESSAGES_ON_MAP_BOTTOM; ubLinesPrinted++ ) diff --git a/local.h b/local.h index cb26ba3f..aa78a6d5 100644 --- a/local.h +++ b/local.h @@ -1,3 +1,4 @@ +// WANNE 2 #ifndef __LOCAL_DEFINES_ #define __LOCAL_DEFINES_ @@ -28,6 +29,9 @@ extern int iResolution; // Resolution id from the ini file extern int iScreenWidthOffset; extern int iScreenHeightOffset; +// WANNE 2 +extern BOOLEAN fDisplayOverheadMap; + #define PIXEL_DEPTH 16 //