Encounter.c 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321
  1. /***********************************************************************
  2. *
  3. * SPACE TRADER 1.2.0
  4. *
  5. * Encounter.c
  6. *
  7. * Copyright (C) 2000-2002 Pieter Spronck, All Rights Reserved
  8. *
  9. * Additional coding by Sam Anderson (rulez2@home.com)
  10. * Additional coding by Samuel Goldstein (palm@fogbound.net)
  11. *
  12. * Some code of Matt Lee's Dope Wars program has been used.
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License
  16. * as published by the Free Software Foundation; either version 2
  17. * of the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  27. *
  28. * You can contact the author at space_trader@hotmail.com
  29. *
  30. * For those who are familiar with the classic game Elite: many of the
  31. * ideas in Space Trader are heavily inspired by Elite.
  32. *
  33. **********************************************************************/
  34. // *************************************************************************
  35. // Encounter.c - Functions in this module:
  36. // --------------------------------------------------------------------
  37. //
  38. // Boolean EncounterFormHandleEvent ( EventPtr eventP )
  39. //
  40. // --------------------------------------------------------------------
  41. // Static Local Functions
  42. // --------------------------------------------------------------------
  43. // Boolean ExecuteAttack( SHIP* Attacker, SHIP* Defender, Boolean Flees, Boolean CommanderUnderAttack )
  44. // int ExecuteAction( Boolean CommanderFlees )
  45. // long TotalWeapons( SHIP* Sh )
  46. // long TotalShields( SHIP* Sh )
  47. // long TotalShieldStrength( SHIP* Sh )
  48. // void ShowShip( SHIP* Sh, int offset, Boolean commandersShip )
  49. // void EncounterDisplayShips( void )
  50. // void EscapeWithPod( void )
  51. // void Arrested( void )
  52. // void Scoop( void )
  53. // void EncounterDisplayNextAction( Boolean FirstDisplay )
  54. // void EncounterButtons( void )
  55. //
  56. // -------------------------------------------------------------------------
  57. // Modifications:
  58. // mm/dd/yy - description - author
  59. // 06/30/01 - Police Encounter text changed - SRA
  60. // -------------------------------------------------------------------------
  61. //
  62. // *************************************************************************
  63. #include "external.h"
  64. static Boolean playerShipNeedsUpdate, opponentShipNeedsUpdate;
  65. #ifdef HWATTACK
  66. int hwbutton[4];
  67. #endif
  68. #define BELOW35 (romVersion < sysMakeROMVersion( 3, 5, 0, sysROMStageRelease, 0 ))
  69. // *************************************************************************
  70. // Calculate Bounty
  71. // *************************************************************************
  72. static long GetBounty( SHIP* Sh )
  73. {
  74. long Bounty = EnemyShipPrice( Sh );
  75. Bounty /= 200;
  76. Bounty /= 25;
  77. Bounty *= 25;
  78. if (Bounty <= 0)
  79. Bounty = 25;
  80. if (Bounty > 2500)
  81. Bounty = 2500;
  82. return Bounty;
  83. }
  84. // *************************************************************************
  85. // Buttons on the encounter screen
  86. // *************************************************************************
  87. static void EncounterButtons( void )
  88. {
  89. FormPtr frmP;
  90. frmP = FrmGetActiveForm();
  91. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterAttackButton ) );
  92. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterSurrenderButton ) );
  93. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterIgnoreButton ) );
  94. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterFleeButton ) );
  95. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterSubmitButton ) );
  96. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterBribeButton ) );
  97. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterPlunderButton ) );
  98. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterInterruptButton ) );
  99. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterDrinkButton ) );
  100. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterBoardButton ) );
  101. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterMeetButton ) );
  102. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterYieldButton ) );
  103. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterTradeButton ) );
  104. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterAttackBitMap ) );
  105. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterAttack2BitMap ) );
  106. if (AutoAttack || AutoFlee)
  107. {
  108. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterInterruptButton ) );
  109. AttackIconStatus = !AttackIconStatus;
  110. if (AttackIconStatus)
  111. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterAttackBitMap ) );
  112. else
  113. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterAttack2BitMap ) );
  114. }
  115. if (EncounterType == POLICEINSPECTION)
  116. {
  117. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterAttackButton ) );
  118. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterFleeButton ) );
  119. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterSubmitButton ) );
  120. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterBribeButton ) );
  121. #ifdef HWATTACK
  122. hwbutton[0] = EncounterAttackButton;
  123. hwbutton[1] = EncounterFleeButton;
  124. hwbutton[2] = EncounterSubmitButton;
  125. hwbutton[3] = EncounterBribeButton;
  126. #endif
  127. }
  128. else if (EncounterType == POSTMARIEPOLICEENCOUNTER)
  129. {
  130. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterAttackButton ) );
  131. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterFleeButton ) );
  132. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterYieldButton ) );
  133. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterBribeButton ) );
  134. #ifdef HWATTACK
  135. hwbutton[0] = EncounterAttackButton;
  136. hwbutton[1] = EncounterFleeButton;
  137. hwbutton[2] = EncounterYieldButton;
  138. hwbutton[3] = EncounterBribeButton;
  139. #endif
  140. }
  141. else if (EncounterType == POLICEFLEE || EncounterType == TRADERFLEE ||
  142. EncounterType == PIRATEFLEE)
  143. {
  144. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterAttackButton ) );
  145. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterIgnoreButton ) );
  146. #ifdef HWATTACK
  147. hwbutton[0] = EncounterAttackButton;
  148. hwbutton[1] = EncounterIgnoreButton;
  149. hwbutton[2] = 0;
  150. hwbutton[3] = 0;
  151. #endif
  152. }
  153. else if (EncounterType == PIRATEATTACK || EncounterType == POLICEATTACK ||
  154. EncounterType == SCARABATTACK)
  155. {
  156. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterAttackButton ) );
  157. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterFleeButton ) );
  158. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterSurrenderButton ) );
  159. #ifdef HWATTACK
  160. hwbutton[0] = EncounterAttackButton;
  161. hwbutton[1] = EncounterFleeButton;
  162. hwbutton[2] = EncounterSurrenderButton;
  163. hwbutton[3] = 0;
  164. #endif
  165. }
  166. else if (EncounterType == FAMOUSCAPATTACK)
  167. {
  168. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterAttackButton ) );
  169. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterFleeButton ) );
  170. #ifdef HWATTACK
  171. hwbutton[0] = EncounterAttackButton;
  172. hwbutton[1] = EncounterFleeButton;
  173. hwbutton[2] = 0;
  174. hwbutton[3] = 0;
  175. #endif
  176. }
  177. else if (EncounterType == TRADERATTACK ||
  178. EncounterType == SPACEMONSTERATTACK || EncounterType == DRAGONFLYATTACK)
  179. {
  180. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterAttackButton ) );
  181. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterFleeButton ) );
  182. #ifdef HWATTACK
  183. hwbutton[0] = EncounterAttackButton;
  184. hwbutton[1] = EncounterFleeButton;
  185. hwbutton[2] = 0;
  186. hwbutton[3] = 0;
  187. #endif
  188. }
  189. else if (EncounterType == TRADERIGNORE || EncounterType == POLICEIGNORE ||
  190. EncounterType == PIRATEIGNORE ||
  191. EncounterType == SPACEMONSTERIGNORE || EncounterType == DRAGONFLYIGNORE ||
  192. EncounterType == SCARABIGNORE)
  193. {
  194. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterAttackButton ) );
  195. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterIgnoreButton ) );
  196. #ifdef HWATTACK
  197. hwbutton[0] = EncounterAttackButton;
  198. hwbutton[1] = EncounterIgnoreButton;
  199. hwbutton[2] = 0;
  200. hwbutton[3] = 0;
  201. #endif
  202. }
  203. else if (EncounterType == TRADERSURRENDER || EncounterType == PIRATESURRENDER)
  204. {
  205. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterAttackButton ) );
  206. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterPlunderButton ) );
  207. #ifdef HWATTACK
  208. hwbutton[0] = EncounterAttackButton;
  209. hwbutton[1] = EncounterPlunderButton;
  210. hwbutton[2] = 0;
  211. hwbutton[3] = 0;
  212. #endif
  213. }
  214. else if (EncounterType == MARIECELESTEENCOUNTER)
  215. {
  216. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterBoardButton ) );
  217. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterIgnoreButton ) );
  218. #ifdef HWATTACK
  219. hwbutton[0] = EncounterBoardButton;
  220. hwbutton[1] = EncounterIgnoreButton;
  221. hwbutton[2] = 0;
  222. hwbutton[3] = 0;
  223. #endif
  224. }
  225. else if (ENCOUNTERFAMOUS(EncounterType))
  226. {
  227. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterAttackButton ) );
  228. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterIgnoreButton ) );
  229. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterMeetButton ) );
  230. #ifdef HWATTACK
  231. hwbutton[0] = EncounterAttackButton;
  232. hwbutton[1] = EncounterIgnoreButton;
  233. hwbutton[2] = EncounterMeetButton;
  234. hwbutton[3] = 0;
  235. #endif
  236. }
  237. else if (EncounterType == BOTTLEOLDENCOUNTER ||
  238. EncounterType == BOTTLEGOODENCOUNTER)
  239. {
  240. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterDrinkButton ) );
  241. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterIgnoreButton ) );
  242. #ifdef HWATTACK
  243. hwbutton[0] = EncounterDrinkButton;
  244. hwbutton[1] = EncounterIgnoreButton;
  245. hwbutton[2] = 0;
  246. hwbutton[3] = 0;
  247. #endif
  248. }
  249. else if (EncounterType == TRADERSELL || EncounterType == TRADERBUY)
  250. {
  251. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterAttackButton ) );
  252. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterIgnoreButton ) );
  253. FrmShowObject( frmP, FrmGetObjectIndex( frmP, EncounterTradeButton ) );
  254. #ifdef HWATTACK
  255. hwbutton[0] = EncounterAttackButton;
  256. hwbutton[1] = EncounterIgnoreButton;
  257. hwbutton[2] = EncounterTradeButton;
  258. hwbutton[3] = 0;
  259. #endif
  260. }
  261. if (!TextualEncounters)
  262. {
  263. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterYouLabel ) );
  264. FrmHideObject( frmP, FrmGetObjectIndex( frmP, EncounterOpponentLabel ) );
  265. }
  266. }
  267. // *************************************************************************
  268. // Display on the encounter screen what the next action will be
  269. // *************************************************************************
  270. static void EncounterDisplayNextAction( Boolean FirstDisplay )
  271. {
  272. if (EncounterType == POLICEINSPECTION)
  273. {
  274. DrawChars( "The police summon you to submit", 6, 106 );
  275. DrawChars( "to an inspection.", 6, 119 );
  276. }
  277. else if (EncounterType == POSTMARIEPOLICEENCOUNTER)
  278. {
  279. DrawChars( "\"We know you removed illegal", 6, 93 );
  280. DrawChars( "goods from the Marie Celeste.", 6,106 );
  281. DrawChars( "You must give them up at once!\"", 6, 119 );
  282. }
  283. else if (FirstDisplay && EncounterType == POLICEATTACK &&
  284. PoliceRecordScore > CRIMINALSCORE)
  285. {
  286. DrawChars( "The police hail they want", 6, 106 );
  287. DrawChars( "you to surrender.", 6, 119 );
  288. }
  289. else if (EncounterType == POLICEFLEE || EncounterType == TRADERFLEE ||
  290. EncounterType == PIRATEFLEE)
  291. DrawChars( "Your opponent is fleeing.", 6, 106 );
  292. else if (EncounterType == PIRATEATTACK || EncounterType == POLICEATTACK ||
  293. EncounterType == TRADERATTACK || EncounterType == SPACEMONSTERATTACK ||
  294. EncounterType == DRAGONFLYATTACK || EncounterType == SCARABATTACK ||
  295. EncounterType == FAMOUSCAPATTACK)
  296. DrawChars( "Your opponent attacks.", 6, 106 );
  297. else if (EncounterType == TRADERIGNORE || EncounterType == POLICEIGNORE ||
  298. EncounterType == SPACEMONSTERIGNORE || EncounterType == DRAGONFLYIGNORE ||
  299. EncounterType == PIRATEIGNORE || EncounterType == SCARABIGNORE)
  300. {
  301. if (Cloaked( &Ship, &Opponent ))
  302. DrawChars( "It doesn't notice you.", 6, 106 );
  303. else
  304. DrawChars( "It ignores you.", 6, 106 );
  305. }
  306. else if (EncounterType == TRADERSELL || EncounterType == TRADERBUY)
  307. {
  308. DrawChars( "You are hailed with an offer", 6, 106 );
  309. DrawChars( "to trade goods.", 6, 119 );
  310. }
  311. else if (EncounterType == TRADERSURRENDER || EncounterType == PIRATESURRENDER)
  312. {
  313. DrawChars( "Your opponent hails that he", 6, 106 );
  314. DrawChars( "surrenders to you.", 6, 119 );
  315. }
  316. else if (EncounterType == MARIECELESTEENCOUNTER)
  317. {
  318. DrawChars( "The Marie Celeste appears to", 6, 106 );
  319. DrawChars( "be completely abandoned.", 6, 119 );
  320. }
  321. else if (ENCOUNTERFAMOUS(EncounterType) && EncounterType != FAMOUSCAPATTACK)
  322. {
  323. DrawChars( "The Captain requests a brief", 6, 106 );
  324. DrawChars( "meeting with you.", 6, 119 );
  325. }
  326. else if (EncounterType == BOTTLEOLDENCOUNTER ||
  327. EncounterType == BOTTLEGOODENCOUNTER)
  328. {
  329. DrawChars( "It appears to be a rare bottle", 6, 106);
  330. DrawChars( "of Captain Marmoset's Skill Tonic!", 6, 119);
  331. }
  332. }
  333. // *************************************************************************
  334. // You can pick up cannisters left by a destroyed ship
  335. // *************************************************************************
  336. static void Scoop( void )
  337. {
  338. int d, ret;
  339. FormPtr frm;
  340. // Chance 50% to pick something up on Normal level, 33% on Hard level, 25% on
  341. // Impossible level, and 100% on Easy or Beginner
  342. if (Difficulty >= NORMAL)
  343. if (GetRandom( Difficulty ) != 1)
  344. return;
  345. // More chance to pick up a cheap good
  346. d = GetRandom( MAXTRADEITEM );
  347. if (d >= 5)
  348. d = GetRandom( MAXTRADEITEM );
  349. frm = FrmInitForm( PickCannisterForm );
  350. StrCopy( SBuf, "ship, labeled " );
  351. StrCat( SBuf, Tradeitem[d].Name );
  352. StrCat( SBuf, ", drifts" );
  353. setLabelText( frm, PickCannisterCannisterLabel, SBuf );
  354. ret = FrmDoDialog( frm );
  355. FrmDeleteForm( frm );
  356. if (ret == PickCannisterPickItUpButton)
  357. {
  358. if (FilledCargoBays() >= TotalCargoBays())
  359. {
  360. if (FrmAlert( NoRoomToScoopAlert ) == NoRoomToScoopLetitgo)
  361. return;
  362. frm = FrmInitForm( DumpCargoForm );
  363. FrmSetEventHandler( frm, DiscardCargoFormHandleEvent );
  364. FrmDoDialog( frm );
  365. FrmDeleteForm( frm );
  366. }
  367. if (FilledCargoBays() < TotalCargoBays())
  368. ++Ship.Cargo[d];
  369. else
  370. FrmAlert( NoDumpNoScoopAlert );
  371. }
  372. }
  373. // *************************************************************************
  374. // Calculate total possible shield strength
  375. // *************************************************************************
  376. static long TotalShields( SHIP* Sh )
  377. {
  378. int i;
  379. long j;
  380. j = 0;
  381. for (i=0; i<MAXSHIELD; ++i)
  382. {
  383. if (Sh->Shield[i] < 0)
  384. break;
  385. j += Shieldtype[Sh->Shield[i]].Power;
  386. }
  387. return j;
  388. }
  389. // *************************************************************************
  390. // Calculate total shield strength
  391. // *************************************************************************
  392. static long TotalShieldStrength( SHIP* Sh )
  393. {
  394. int i;
  395. long k;
  396. k = 0;
  397. for (i=0; i<MAXSHIELD; ++i)
  398. {
  399. if (Sh->Shield[i] < 0)
  400. break;
  401. k += Sh->ShieldStrength[i];
  402. }
  403. return k;
  404. }
  405. // *************************************************************************
  406. // Show the ship stats on the encounter screen
  407. // *************************************************************************
  408. void ShowShip( SHIP* Sh, int offset, Boolean commandersShip )
  409. {
  410. int x, y, x2, y2, startdamage, startshield, icon;
  411. RectangleType bounds;
  412. FntSetFont( stdFont );
  413. if (TextualEncounters)
  414. {
  415. EraseRectangle( offset, 32, 70, 38 );
  416. DrawChars( Shiptype[Sh->Type].Name, offset, 32 );
  417. if (ENCOUNTERMONSTER( EncounterType ) && offset > 10)
  418. StrCopy( SBuf, "Hide at " );
  419. else
  420. StrCopy( SBuf, "Hull at " );
  421. if (commandersShip)
  422. StrIToA( SBuf2, ((Sh->Hull * 100) / GetHullStrength()) );
  423. else
  424. StrIToA( SBuf2, ((Sh->Hull * 100) / Shiptype[Sh->Type].HullStrength) );
  425. StrCat( SBuf, SBuf2 );
  426. StrCat( SBuf, "%" );
  427. DrawChars( SBuf, offset, 45 );
  428. if (Sh->Shield[0] < 0)
  429. StrCopy( SBuf, "No shields" );
  430. else
  431. {
  432. StrCopy( SBuf, "Shields at " );
  433. if (TotalShields( Sh ) > 0)
  434. StrIToA( SBuf2, ((TotalShieldStrength( Sh ) * 100) / TotalShields( Sh )) );
  435. else
  436. StrCopy( SBuf2, "0" );
  437. StrCat( SBuf, SBuf2 );
  438. StrCat( SBuf, "%" );
  439. }
  440. DrawChars( SBuf, offset, 58 );
  441. }
  442. else
  443. {
  444. EraseRectangle( offset, 18, 70, 52 );
  445. x = offset + ((64 - (GetBitmapWidth( ShipBmpPtr[Sh->Type] ))>>1));
  446. y = 18 + ((52 - (GetBitmapHeight( ShipBmpPtr[Sh->Type] ))>>1));
  447. x2 = offset + ((64 - (GetBitmapWidth( ShieldedShipBmpPtr[Sh->Type] ))>>1));
  448. y2 = 18 + ((52 - (GetBitmapHeight( ShieldedShipBmpPtr[Sh->Type] ))>>1));
  449. if (commandersShip)
  450. {
  451. startdamage = x + GetBitmapWidth( ShipBmpPtr[Sh->Type] ) -
  452. ((Sh->Hull * GetBitmapWidth( ShipBmpPtr[Sh->Type] )) / GetHullStrength());
  453. }
  454. else
  455. {
  456. startdamage = x + GetBitmapWidth( ShipBmpPtr[Sh->Type] ) -
  457. ((Sh->Hull * GetBitmapWidth( ShipBmpPtr[Sh->Type] )) / Shiptype[Sh->Type].HullStrength);
  458. }
  459. startshield = x2 + GetBitmapWidth( ShieldedShipBmpPtr[Sh->Type] ) -
  460. (Sh->Shield[0] < 0 ? 0 :
  461. (TotalShieldStrength( Sh ) * GetBitmapWidth( ShieldedShipBmpPtr[Sh->Type] )) / TotalShields( Sh ) );
  462. bounds.topLeft.x = x2;
  463. bounds.topLeft.y = 18;
  464. bounds.extent.x = min( startdamage, startshield ) - x2;
  465. bounds.extent.y = 52;
  466. WinSetClip( &bounds );
  467. WinDrawBitmap( DamagedShipBmpPtr[Sh->Type], x, y );
  468. WinResetClip();
  469. bounds.topLeft.x = min( startdamage, startshield );
  470. bounds.extent.x = max( startdamage, startshield ) - x2;
  471. WinSetClip( &bounds );
  472. if (startdamage < startshield)
  473. WinDrawBitmap( ShipBmpPtr[Sh->Type], x, y );
  474. else
  475. WinDrawBitmap( DamagedShieldedShipBmpPtr[Sh->Type], x2, y2 );
  476. WinResetClip();
  477. bounds.topLeft.x = max( startdamage, startshield );
  478. bounds.extent.x = GetBitmapWidth( ShieldedShipBmpPtr[Sh->Type] );
  479. WinSetClip( &bounds );
  480. WinDrawBitmap( ShieldedShipBmpPtr[Sh->Type], x2, y2 );
  481. WinResetClip();
  482. if (offset > 10)
  483. {
  484. icon = -1;
  485. if (ENCOUNTERPIRATE( EncounterType ))
  486. {
  487. if (Sh->Type == MANTISTYPE)
  488. icon = 3;
  489. else
  490. icon = 0;
  491. }
  492. else if (ENCOUNTERPOLICE( EncounterType ))
  493. icon = 1;
  494. else if (ENCOUNTERTRADER( EncounterType ))
  495. icon = 2;
  496. else if (EncounterType == CAPTAINHUIEENCOUNTER ||
  497. EncounterType == MARIECELESTEENCOUNTER ||
  498. EncounterType == CAPTAINAHABENCOUNTER ||
  499. EncounterType == CAPTAINCONRADENCOUNTER)
  500. icon = 4;
  501. if (icon >= 0)
  502. WinDrawBitmap( IconBmpPtr[icon], 143, 13 );
  503. }
  504. }
  505. }
  506. // *************************************************************************
  507. // Display on the encounter screen the ships (and also wipe it)
  508. // *************************************************************************
  509. static void EncounterDisplayShips( void )
  510. {
  511. if (opponentShipNeedsUpdate)
  512. {
  513. opponentShipNeedsUpdate = false;
  514. ShowShip( &Opponent, (TextualEncounters ? 84 : 80), false );
  515. }
  516. if (playerShipNeedsUpdate)
  517. {
  518. playerShipNeedsUpdate = false;
  519. ShowShip( &Ship, 6, true );
  520. }
  521. EraseRectangle( 5, 75, 151, 64 );
  522. }
  523. // *************************************************************************
  524. // Your escape pod ejects you
  525. // *************************************************************************
  526. void EscapeWithPod( void )
  527. {
  528. FrmAlert( EscapePodActivatedAlert );
  529. if (ScarabStatus == 3)
  530. ScarabStatus = 0;
  531. Arrival();
  532. if (ReactorStatus > 0 && ReactorStatus < 21)
  533. {
  534. FrmAlert( ReactorDestroyedAlert );
  535. ReactorStatus = 0;
  536. }
  537. if (JaporiDiseaseStatus == 1)
  538. {
  539. FrmAlert( AntidoteDestroyedAlert );
  540. JaporiDiseaseStatus = 0;
  541. }
  542. if (ArtifactOnBoard)
  543. {
  544. FrmAlert( ArtifactNotSavedAlert );
  545. ArtifactOnBoard = false;
  546. }
  547. if (JarekStatus == 1)
  548. {
  549. FrmAlert( JarekTakenHomeAlert );
  550. JarekStatus = 0;
  551. }
  552. if (WildStatus == 1)
  553. {
  554. FrmAlert( WildArrestedAlert );
  555. PoliceRecordScore += CAUGHTWITHWILDSCORE;
  556. addNewsEvent(WILDARRESTED);
  557. WildStatus = 0;
  558. }
  559. if (Ship.Tribbles > 0)
  560. {
  561. FrmAlert( TribbleSurvivedAlert );
  562. Ship.Tribbles = 0;
  563. }
  564. if (Insurance)
  565. {
  566. FrmAlert( InsurancePaysAlert );
  567. Credits += CurrentShipPriceWithoutCargo( true );
  568. }
  569. FrmAlert( FleaBuiltAlert );
  570. if (Credits > 500)
  571. Credits -= 500;
  572. else
  573. {
  574. Debt += (500 - Credits);
  575. Credits = 0;
  576. }
  577. IncDays( 3 );
  578. CreateFlea();
  579. CurForm = SystemInformationForm;
  580. FrmGotoForm( CurForm );
  581. }
  582. // *************************************************************************
  583. // You get arrested
  584. // *************************************************************************
  585. static void Arrested( void )
  586. {
  587. FormPtr frm;
  588. long Fine, Imprisonment;
  589. int i;
  590. Fine = ((1 + (((CurrentWorth() * min( 80, -PoliceRecordScore )) / 100) / 500)) * 500);
  591. if (WildStatus == 1)
  592. {
  593. Fine *= 1.05;
  594. }
  595. Imprisonment = max( 30, -PoliceRecordScore );
  596. FrmAlert( ArrestedAlert );
  597. frm = FrmInitForm( ConvictionForm );
  598. StrCopy( SBuf, "You are convicted to " );
  599. StrIToA( SBuf2, Imprisonment );
  600. StrCat( SBuf, SBuf2 );
  601. StrCat( SBuf, " days in" );
  602. setLabelText( frm, ConvictionImprisonmentLabel, SBuf );
  603. StrCopy( SBuf, "prison and a fine of " );
  604. StrIToA( SBuf2, Fine );
  605. StrCat( SBuf, SBuf2 );
  606. StrCat( SBuf, " credits." );
  607. setLabelText( frm, ConvictionFineLabel, SBuf );
  608. FrmDoDialog( frm );
  609. FrmDeleteForm( frm );
  610. if (Ship.Cargo[NARCOTICS] > 0 || Ship.Cargo[FIREARMS] > 0)
  611. {
  612. FrmAlert( ImpoundAlert );
  613. Ship.Cargo[NARCOTICS] = 0;
  614. Ship.Cargo[FIREARMS] = 0;
  615. }
  616. if (Insurance)
  617. {
  618. FrmAlert( InsuranceLostAlert );
  619. Insurance = false;
  620. NoClaim = 0;
  621. }
  622. if (Ship.Crew[1] >= 0)
  623. {
  624. FrmAlert( MercenariesLeaveAlert );
  625. for (i=1; i<MAXCREW; ++i)
  626. Ship.Crew[i] = -1;
  627. }
  628. if (JaporiDiseaseStatus == 1)
  629. {
  630. FrmAlert( AntidoteRemovedAlert );
  631. JaporiDiseaseStatus = 2;
  632. }
  633. if (JarekStatus == 1)
  634. {
  635. FrmAlert( JarekTakenHomeAlert );
  636. JarekStatus = 0;
  637. }
  638. if (WildStatus == 1)
  639. {
  640. FrmAlert( WildArrestedAlert );
  641. addNewsEvent(WILDARRESTED);
  642. WildStatus = 0;
  643. }
  644. if (ReactorStatus > 0 && ReactorStatus < 21)
  645. {
  646. FrmAlert( PoliceConfiscateReactorAlert );
  647. ReactorStatus = 0;
  648. }
  649. Arrival();
  650. IncDays( Imprisonment );
  651. if (Credits >= Fine)
  652. Credits -= Fine;
  653. else
  654. {
  655. Credits += CurrentShipPrice( true );
  656. if (Credits >= Fine)
  657. Credits -= Fine;
  658. else
  659. Credits = 0;
  660. FrmAlert( ShipSoldAlert );
  661. if (Ship.Tribbles > 0)
  662. {
  663. FrmAlert( TribblesSoldAlert );
  664. Ship.Tribbles = 0;
  665. }
  666. FrmAlert( FleaReceivedAlert );
  667. CreateFlea();
  668. }
  669. PoliceRecordScore = DUBIOUSSCORE;
  670. if (Debt > 0)
  671. {
  672. if (Credits >= Debt)
  673. {
  674. Credits -= Debt;
  675. Debt = 0;
  676. }
  677. else
  678. {
  679. Debt -= Credits;
  680. Credits = 0;
  681. }
  682. }
  683. for (i=0; i<Imprisonment; ++i)
  684. PayInterest();
  685. CurForm = SystemInformationForm;
  686. FrmGotoForm( CurForm );
  687. }
  688. // *************************************************************************
  689. // An attack: Attacker attacks Defender, Flees indicates if Defender is fleeing
  690. // *************************************************************************
  691. static Boolean ExecuteAttack( SHIP* Attacker, SHIP* Defender, Boolean Flees, Boolean CommanderUnderAttack )
  692. {
  693. long Damage, prevDamage;
  694. int i;
  695. // On beginner level, if you flee, you will escape unharmed.
  696. if (Difficulty == BEGINNER && CommanderUnderAttack && Flees)
  697. return false;
  698. // Fighterskill attacker is pitted against pilotskill defender; if defender
  699. // is fleeing the attacker has a free shot, but the chance to hit is smaller
  700. if (GetRandom( FighterSkill( Attacker ) + Shiptype[Defender->Type].Size ) <
  701. (Flees ? 2 : 1) * GetRandom( 5 + (PilotSkill( Defender ) >> 1) ))
  702. // Misses
  703. return false;
  704. if (TotalWeapons( Attacker, -1, -1) <= 0)
  705. Damage = 0L;
  706. else if (Defender->Type == SCARABTYPE)
  707. {
  708. if (TotalWeapons( Attacker, PULSELASERWEAPON, PULSELASERWEAPON ) <= 0 &&
  709. TotalWeapons( Attacker, MORGANLASERWEAPON, MORGANLASERWEAPON ) <= 0)
  710. Damage = 0L;
  711. else
  712. Damage = GetRandom( ((TotalWeapons( Attacker, PULSELASERWEAPON, PULSELASERWEAPON ) +
  713. TotalWeapons( Attacker, MORGANLASERWEAPON, MORGANLASERWEAPON )) * (100 + 2*EngineerSkill( Attacker )) / 100) );
  714. }
  715. else
  716. Damage = GetRandom( (TotalWeapons( Attacker, -1, -1 ) * (100 + 2*EngineerSkill( Attacker )) / 100) );
  717. if (Damage <= 0L)
  718. return false;
  719. // Reactor on board -- damage is boosted!
  720. if (CommanderUnderAttack && ReactorStatus > 0 && ReactorStatus < 21)
  721. {
  722. if (Difficulty < NORMAL)
  723. Damage *= 1 + (Difficulty + 1)*0.25;
  724. else
  725. Damage *= 1 + (Difficulty + 1)*0.33;
  726. }
  727. // First, shields are depleted
  728. for (i=0; i<MAXSHIELD; ++i)
  729. {
  730. if (Defender->Shield[i] < 0)
  731. break;
  732. if (Damage <= Defender->ShieldStrength[i])
  733. {
  734. Defender->ShieldStrength[i] -= Damage;
  735. Damage = 0;
  736. break;
  737. }
  738. Damage -= Defender->ShieldStrength[i];
  739. Defender->ShieldStrength[i] = 0;
  740. }
  741. prevDamage = Damage;
  742. // If there still is damage after the shields have been depleted,
  743. // this is subtracted from the hull, modified by the engineering skill
  744. // of the defender.
  745. if (Damage > 0)
  746. {
  747. Damage -= GetRandom( EngineerSkill( Defender ) );
  748. if (Damage <= 0)
  749. Damage = 1;
  750. // At least 2 shots on Normal level are needed to destroy the hull
  751. // (3 on Easy, 4 on Beginner, 1 on Hard or Impossible). For opponents,
  752. // it is always 2.
  753. if (CommanderUnderAttack && ScarabStatus == 3)
  754. Damage = min( Damage, (GetHullStrength()/
  755. (CommanderUnderAttack ? max( 1, (IMPOSSIBLE-Difficulty) ) : 2)) );
  756. else
  757. Damage = min( Damage, (Shiptype[Defender->Type].HullStrength/
  758. (CommanderUnderAttack ? max( 1, (IMPOSSIBLE-Difficulty) ) : 2)) );
  759. Defender->Hull -= Damage;
  760. if (Defender->Hull < 0)
  761. Defender->Hull = 0;
  762. }
  763. if (Damage != prevDamage)
  764. {
  765. if (CommanderUnderAttack)
  766. {
  767. playerShipNeedsUpdate = true;
  768. }
  769. else
  770. {
  771. opponentShipNeedsUpdate = true;
  772. }
  773. }
  774. return true;
  775. }
  776. // *************************************************************************
  777. // A fight round
  778. // Return value indicates whether fight continues into another round
  779. // *************************************************************************
  780. static int ExecuteAction( Boolean CommanderFlees )
  781. {
  782. FormPtr frmP;
  783. Boolean CommanderGotHit, OpponentGotHit;
  784. long OpponentHull, ShipHull;
  785. int y, i, objindex;
  786. int PrevEncounterType;
  787. ControlPtr cp;
  788. CommanderGotHit = false;
  789. OpponentHull = Opponent.Hull;
  790. ShipHull = Ship.Hull;
  791. // Fire shots
  792. if (EncounterType == PIRATEATTACK || EncounterType == POLICEATTACK ||
  793. EncounterType == TRADERATTACK || EncounterType == SPACEMONSTERATTACK ||
  794. EncounterType == DRAGONFLYATTACK || EncounterType == POSTMARIEPOLICEENCOUNTER ||
  795. EncounterType == SCARABATTACK || EncounterType == FAMOUSCAPATTACK)
  796. {
  797. CommanderGotHit = ExecuteAttack( &Opponent, &Ship, CommanderFlees, true );
  798. }
  799. OpponentGotHit = false;
  800. if (!CommanderFlees)
  801. {
  802. if (EncounterType == POLICEFLEE || EncounterType == TRADERFLEE ||
  803. EncounterType == PIRATEFLEE)
  804. {
  805. OpponentGotHit = ExecuteAttack( &Ship, &Opponent, true, false );
  806. }
  807. else
  808. {
  809. OpponentGotHit = ExecuteAttack( &Ship, &Opponent, false, false );
  810. }
  811. }
  812. if (CommanderGotHit)
  813. {
  814. playerShipNeedsUpdate = true;
  815. }
  816. if (OpponentGotHit)
  817. {
  818. opponentShipNeedsUpdate = true;
  819. }
  820. // Determine whether someone gets destroyed
  821. if (Ship.Hull <= 0 && Opponent.Hull <= 0)
  822. {
  823. AutoAttack = false;
  824. AutoFlee = false;
  825. if (EscapePod)
  826. {
  827. EscapeWithPod();
  828. return( true );
  829. }
  830. else
  831. {
  832. FrmAlert( BothDestroyedAlert );
  833. CurForm = DestroyedForm;
  834. FrmGotoForm( CurForm );
  835. }
  836. return false;
  837. }
  838. else if (Opponent.Hull <= 0)
  839. {
  840. AutoAttack = false;
  841. AutoFlee = false;
  842. if (ENCOUNTERPIRATE( EncounterType ) && Opponent.Type != MANTISTYPE && PoliceRecordScore >= DUBIOUSSCORE)
  843. {
  844. frmP = FrmInitForm( BountyForm );
  845. StrCopy( SBuf, "You earned a bounty of " );
  846. // StrIToA( SBuf2, Shiptype[Opponent.Type].Bounty );
  847. StrIToA( SBuf2, GetBounty( &Opponent ) );
  848. StrCat( SBuf, SBuf2 );
  849. StrCat( SBuf, " cr." );
  850. setLabelText( frmP, BountyBountyLabel, SBuf );
  851. FrmDoDialog( frmP );
  852. FrmDeleteForm( frmP );
  853. }
  854. else
  855. {
  856. FrmAlert( OpponentDestroyedAlert );
  857. }
  858. if (ENCOUNTERPOLICE( EncounterType ))
  859. {
  860. ++PoliceKills;
  861. PoliceRecordScore += KILLPOLICESCORE;
  862. }
  863. else if (ENCOUNTERFAMOUS( EncounterType))
  864. {
  865. if (ReputationScore < DANGEROUSREP)
  866. {
  867. ReputationScore = DANGEROUSREP;
  868. }
  869. else
  870. {
  871. ReputationScore += 100;
  872. }
  873. // bump news flag from attacked to ship destroyed
  874. replaceNewsEvent(latestNewsEvent(), latestNewsEvent() + 10);
  875. }
  876. else if (ENCOUNTERPIRATE( EncounterType ))
  877. {
  878. if (Opponent.Type != MANTISTYPE)
  879. {
  880. // Credits += Shiptype[Opponent.Type].Bounty;
  881. Credits += GetBounty( &Opponent );
  882. PoliceRecordScore += KILLPIRATESCORE;
  883. Scoop();
  884. }
  885. ++PirateKills;
  886. }
  887. else if (ENCOUNTERTRADER( EncounterType ))
  888. {
  889. ++TraderKills;
  890. PoliceRecordScore += KILLTRADERSCORE;
  891. Scoop();
  892. }
  893. else if (ENCOUNTERMONSTER( EncounterType ))
  894. {
  895. ++PirateKills;
  896. PoliceRecordScore += KILLPIRATESCORE;
  897. MonsterStatus = 2;
  898. }
  899. else if (ENCOUNTERDRAGONFLY( EncounterType ))
  900. {
  901. ++PirateKills;
  902. PoliceRecordScore += KILLPIRATESCORE;
  903. DragonflyStatus = 5;
  904. }
  905. else if (ENCOUNTERSCARAB( EncounterType ))
  906. {
  907. ++PirateKills;
  908. PoliceRecordScore += KILLPIRATESCORE;
  909. ScarabStatus = 2;
  910. }
  911. ReputationScore += 1 + (Opponent.Type>>1);
  912. return false;
  913. }
  914. else if (Ship.Hull <= 0)
  915. {
  916. AutoAttack = false;
  917. AutoFlee = false;
  918. if (EscapePod)
  919. {
  920. EscapeWithPod();
  921. return( true );
  922. }
  923. else
  924. {
  925. FrmAlert( ShipDestroyedAlert );
  926. CurForm = DestroyedForm;
  927. FrmGotoForm( CurForm );
  928. }
  929. return false;
  930. }
  931. // Determine whether someone gets away.
  932. if (CommanderFlees)
  933. {
  934. if (Difficulty == BEGINNER)
  935. {
  936. AutoAttack = false;
  937. AutoFlee = false;
  938. FrmAlert( YouEscapedAlert );
  939. if (ENCOUNTERMONSTER( EncounterType ))
  940. MonsterHull = Opponent.Hull;
  941. return false;
  942. }
  943. else if ((GetRandom( 7 ) + (PilotSkill( &Ship ) / 3)) * 2 >=
  944. GetRandom( PilotSkill( &Opponent ) ) * (2 + Difficulty))
  945. {
  946. AutoAttack = false;
  947. AutoFlee = false;
  948. if (CommanderGotHit)
  949. {
  950. ShowShip( &Ship, 6, true );
  951. frmP = FrmGetActiveForm();
  952. for (i=0; i<TRIBBLESONSCREEN; ++i)
  953. {
  954. objindex = FrmGetObjectIndex( frmP, EncounterTribble0Button + i );
  955. cp = (ControlPtr)FrmGetObjectPtr( frmP, objindex );
  956. CtlDrawControl( cp );
  957. }
  958. FrmAlert( YouEscapedWithDamageAlert );
  959. }
  960. else
  961. FrmAlert( YouEscapedAlert );
  962. if (ENCOUNTERMONSTER( EncounterType ))
  963. MonsterHull = Opponent.Hull;
  964. return false;
  965. }
  966. }
  967. else if (EncounterType == POLICEFLEE || EncounterType == TRADERFLEE ||
  968. EncounterType == PIRATEFLEE || EncounterType == TRADERSURRENDER ||
  969. EncounterType == PIRATESURRENDER)
  970. {
  971. if (GetRandom( PilotSkill( &Ship ) ) * 4 <=
  972. GetRandom( (7 + (PilotSkill( &Opponent ) / 3))) * 2)
  973. {
  974. AutoAttack = false;
  975. AutoFlee = false;
  976. FrmAlert( OpponentEscapedAlert );
  977. return false;
  978. }
  979. }
  980. // Determine whether the opponent's actions must be changed
  981. PrevEncounterType = EncounterType;
  982. if (Opponent.Hull < OpponentHull)
  983. {
  984. if (ENCOUNTERPOLICE( EncounterType ))
  985. {
  986. if (Opponent.Hull < OpponentHull >> 1)
  987. if (Ship.Hull < ShipHull >> 1)
  988. {
  989. if (GetRandom( 10 ) > 5)
  990. EncounterType = POLICEFLEE;
  991. }
  992. else
  993. EncounterType = POLICEFLEE;
  994. }
  995. else if (EncounterType == POSTMARIEPOLICEENCOUNTER)
  996. {
  997. EncounterType = POLICEATTACK;
  998. }
  999. else if (ENCOUNTERPIRATE( EncounterType ))
  1000. {
  1001. if (Opponent.Hull < (OpponentHull * 2) / 3)
  1002. {
  1003. if (Ship.Hull < (ShipHull * 2) / 3)
  1004. {
  1005. if (GetRandom( 10 ) > 3)
  1006. EncounterType = PIRATEFLEE;
  1007. }
  1008. else
  1009. {
  1010. EncounterType = PIRATEFLEE;
  1011. if (GetRandom( 10 ) > 8 && Opponent.Type < MAXSHIPTYPE)
  1012. EncounterType = PIRATESURRENDER;
  1013. }
  1014. }
  1015. }
  1016. else if (ENCOUNTERTRADER( EncounterType ))
  1017. {
  1018. if (Opponent.Hull < (OpponentHull * 2) / 3)
  1019. {
  1020. if (GetRandom( 10 ) > 3)
  1021. EncounterType = TRADERSURRENDER;
  1022. else
  1023. EncounterType = TRADERFLEE;
  1024. }
  1025. else if (Opponent.Hull < (OpponentHull * 9) / 10)
  1026. {
  1027. if (Ship.Hull < (ShipHull * 2) / 3)
  1028. {
  1029. // If you get damaged a lot, the trader tends to keep shooting
  1030. if (GetRandom( 10 ) > 7)
  1031. EncounterType = TRADERFLEE;
  1032. }
  1033. else if (Ship.Hull < (ShipHull * 9) / 10)
  1034. {
  1035. if (GetRandom( 10 ) > 3)
  1036. EncounterType = TRADERFLEE;
  1037. }
  1038. else
  1039. EncounterType = TRADERFLEE;
  1040. }
  1041. }
  1042. }
  1043. if (PrevEncounterType != EncounterType)
  1044. {
  1045. if (!(AutoAttack &&
  1046. (EncounterType == TRADERFLEE || EncounterType == PIRATEFLEE || EncounterType == POLICEFLEE)))
  1047. AutoAttack = false;
  1048. AutoFlee = false;
  1049. }
  1050. // Show new status
  1051. frmP = FrmGetActiveForm();
  1052. EncounterButtons();
  1053. // FrmDrawForm( frmP );
  1054. EncounterDisplayShips();
  1055. if (ENCOUNTERPOLICE( PrevEncounterType ))
  1056. StrCopy( SBuf2, "police ship" );
  1057. else if (ENCOUNTERPIRATE( PrevEncounterType ))
  1058. {
  1059. if (Opponent.Type == MANTISTYPE)
  1060. StrCopy( SBuf2, "alien ship" );
  1061. else
  1062. StrCopy( SBuf2, "pirate ship" );
  1063. }
  1064. else if (ENCOUNTERTRADER( PrevEncounterType ))
  1065. StrCopy( SBuf2, "trader ship" );
  1066. else if (ENCOUNTERMONSTER( PrevEncounterType ))
  1067. StrCopy( SBuf2, "monster" );
  1068. else if (ENCOUNTERDRAGONFLY( PrevEncounterType ))
  1069. StrCopy( SBuf2, "Dragonfly" );
  1070. else if (ENCOUNTERSCARAB( PrevEncounterType ))
  1071. StrCopy( SBuf2, "Scarab" );
  1072. else if (ENCOUNTERFAMOUS( PrevEncounterType))
  1073. StrCopy( SBuf2, "Captain");
  1074. y = 75;
  1075. if (CommanderGotHit)
  1076. {
  1077. StrCopy( SBuf, "The " );
  1078. StrCat( SBuf, SBuf2 );
  1079. StrCat( SBuf, " hits you." );
  1080. DrawChars( SBuf, 6, y );
  1081. y += 13;
  1082. }
  1083. if (!(PrevEncounterType == POLICEFLEE || PrevEncounterType == TRADERFLEE ||
  1084. PrevEncounterType == PIRATEFLEE) && !CommanderGotHit)
  1085. {
  1086. StrCopy( SBuf, "The " );
  1087. StrCat( SBuf, SBuf2 );
  1088. StrCat( SBuf, " missed you." );
  1089. DrawChars( SBuf, 6, y );
  1090. y += 13;
  1091. }
  1092. if (OpponentGotHit)
  1093. {
  1094. StrCopy( SBuf, "You hit the " );
  1095. StrCat( SBuf, SBuf2 );
  1096. StrCat( SBuf, "." );
  1097. DrawChars( SBuf, 6, y );
  1098. y += 13;
  1099. }
  1100. if (!CommanderFlees && !OpponentGotHit)
  1101. {
  1102. StrCopy( SBuf, "You missed the " );
  1103. StrCat( SBuf, SBuf2 );
  1104. StrCat( SBuf, "." );
  1105. DrawChars( SBuf, 6, y );
  1106. y += 13;
  1107. }
  1108. if (PrevEncounterType == POLICEFLEE || PrevEncounterType == TRADERFLEE ||
  1109. PrevEncounterType == PIRATEFLEE)
  1110. {
  1111. StrCopy( SBuf, "The " );
  1112. StrCat( SBuf, SBuf2 );
  1113. StrCat( SBuf, " didn't get away." );
  1114. DrawChars( SBuf, 6, y );
  1115. y += 13;
  1116. }
  1117. if (CommanderFlees)
  1118. {
  1119. StrCopy( SBuf, "The " );
  1120. StrCat( SBuf, SBuf2 );
  1121. StrCat( SBuf, " is still following you." );
  1122. DrawChars( SBuf, 6, y );
  1123. y += 13;
  1124. }
  1125. EncounterDisplayNextAction( false );
  1126. for (i=0; i<TRIBBLESONSCREEN; ++i)
  1127. {
  1128. objindex = FrmGetObjectIndex( frmP, EncounterTribble0Button + i );
  1129. cp = (ControlPtr)FrmGetObjectPtr( frmP, objindex );
  1130. CtlDrawControl( cp );
  1131. }
  1132. return true;
  1133. }
  1134. // *************************************************************************
  1135. // Calculate total possible weapon strength
  1136. // Modified to allow an upper and lower limit on which weapons work.
  1137. // Weapons equal to or between minWeapon and maxWeapon (e.g., PULSELASERWEAPON)
  1138. // will do damage. Use -1 to allow damage from any weapon, which is almost
  1139. // always what you want. SjG
  1140. // *************************************************************************
  1141. long TotalWeapons( SHIP* Sh, int minWeapon, int maxWeapon )
  1142. {
  1143. int i;
  1144. long j;
  1145. j = 0;
  1146. for (i=0; i<MAXWEAPON; ++i)
  1147. {
  1148. if (Sh->Weapon[i] < 0)
  1149. break;
  1150. if ((minWeapon != -1 && Sh->Weapon[i] < minWeapon) ||
  1151. (maxWeapon != -1 && Sh->Weapon[i] > maxWeapon))
  1152. continue;
  1153. j += Weapontype[Sh->Weapon[i]].Power;
  1154. }
  1155. return j;
  1156. }
  1157. static void DrawEncounterForm()
  1158. {
  1159. FormPtr frmP;
  1160. int d, i;
  1161. int objindex;
  1162. ControlPtr cp;
  1163. frmP = FrmGetActiveForm();
  1164. EncounterButtons();
  1165. FrmDrawForm( frmP );
  1166. // This is an ugly hack. It seems to fix a PalmOS 3.0 bug.
  1167. if (BELOW35)
  1168. EncounterButtons();
  1169. playerShipNeedsUpdate=true;
  1170. opponentShipNeedsUpdate=true;
  1171. EncounterDisplayShips();
  1172. EncounterDisplayNextAction( true );
  1173. if (EncounterType == POSTMARIEPOLICEENCOUNTER)
  1174. {
  1175. DrawChars( "You encounter the Customs Police.", 6, 75 );
  1176. }
  1177. else
  1178. {
  1179. StrCopy( SBuf, "At " );
  1180. SBufMultiples( Clicks, "click" );
  1181. StrCat( SBuf, " from " );
  1182. StrCat( SBuf, SolarSystemName[SolarSystem[WarpSystem].NameIndex] );
  1183. StrCat( SBuf, ", you" );
  1184. DrawChars( SBuf, 6, 75 );
  1185. StrCopy( SBuf, "encounter " );
  1186. if (ENCOUNTERPOLICE( EncounterType ))
  1187. StrCat( SBuf, "a police " );
  1188. else if (ENCOUNTERPIRATE( EncounterType ))
  1189. {
  1190. if (Opponent.Type == MANTISTYPE)
  1191. StrCat( SBuf, "an alien " );
  1192. else
  1193. StrCat( SBuf, "a pirate " );
  1194. }
  1195. else if (ENCOUNTERTRADER( EncounterType ))
  1196. StrCat( SBuf, "a trader " );
  1197. else if (ENCOUNTERMONSTER( EncounterType ))
  1198. StrCat( SBuf, " " );
  1199. else if (EncounterType == MARIECELESTEENCOUNTER)
  1200. StrCat(SBuf,"a drifting ship");
  1201. else if (EncounterType == CAPTAINAHABENCOUNTER)
  1202. StrCat(SBuf, "the famous Captain Ahab");
  1203. else if (EncounterType == CAPTAINCONRADENCOUNTER)
  1204. StrCat(SBuf, "Captain Conrad");
  1205. else if (EncounterType == CAPTAINHUIEENCOUNTER)
  1206. StrCat(SBuf, "Captain Huie");
  1207. else if (EncounterType == BOTTLEOLDENCOUNTER || EncounterType == BOTTLEGOODENCOUNTER)
  1208. StrCat(SBuf, "a floating bottle.");
  1209. else
  1210. StrCat( SBuf, "a stolen " );
  1211. if (EncounterType != MARIECELESTEENCOUNTER && EncounterType != CAPTAINAHABENCOUNTER &&
  1212. EncounterType != CAPTAINCONRADENCOUNTER && EncounterType != CAPTAINHUIEENCOUNTER &&
  1213. EncounterType != BOTTLEOLDENCOUNTER && EncounterType != BOTTLEGOODENCOUNTER)
  1214. {
  1215. StrCopy( SBuf2, Shiptype[Opponent.Type].Name );
  1216. SBuf2[0] = TOLOWER( SBuf2[0] );
  1217. StrCat( SBuf, SBuf2 );
  1218. }
  1219. StrCat( SBuf, "." );
  1220. DrawChars( SBuf, 6, 88 );
  1221. }
  1222. d = sqrt( Ship.Tribbles/250 );
  1223. for (i=0; i<d; ++i)
  1224. {
  1225. objindex = FrmGetObjectIndex( frmP, EncounterTribble0Button +
  1226. GetRandom( TRIBBLESONSCREEN ) );
  1227. cp = (ControlPtr)FrmGetObjectPtr( frmP, objindex );
  1228. CtlShowControl( cp );
  1229. }
  1230. }
  1231. // *************************************************************************
  1232. // Encounter screen Event Handler
  1233. // *************************************************************************
  1234. Boolean EncounterFormHandleEvent ( EventPtr eventP )
  1235. {
  1236. Boolean handled = false;
  1237. FormPtr frmP, frm;
  1238. long Fine;
  1239. long Bribe;
  1240. int d, i, j, m, Bays, TotalCargo;
  1241. Handle QuantityH;
  1242. long Blackmail;
  1243. Boolean RedrawButtons = false;
  1244. #ifdef HWATTACK
  1245. EventType event;
  1246. #endif
  1247. switch (eventP->eType)
  1248. {
  1249. case frmOpenEvent:
  1250. case frmUpdateEvent:
  1251. DrawEncounterForm();
  1252. handled = true;
  1253. break;
  1254. #ifdef HWATTACK
  1255. case keyDownEvent:
  1256. if (! UseHWButtons)
  1257. return false;
  1258. MemSet(&event, sizeof(event), 0);
  1259. event.eType = ctlSelectEvent;
  1260. if (eventP->data.keyDown.chr == hard1Chr)
  1261. event.data.ctlSelect.controlID = hwbutton[0];
  1262. else if (eventP->data.keyDown.chr == hard2Chr)
  1263. event.data.ctlSelect.controlID = hwbutton[1];
  1264. else if (eventP->data.keyDown.chr == hard3Chr)
  1265. event.data.ctlSelect.controlID = hwbutton[2];
  1266. else if (eventP->data.keyDown.chr == hard4Chr)
  1267. event.data.ctlSelect.controlID = hwbutton[3];
  1268. if (event.data.ctlSelect.controlID > 0)
  1269. EvtAddEventToQueue(&event);
  1270. else
  1271. return true;
  1272. handled = true;
  1273. break;
  1274. #endif
  1275. case nilEvent:
  1276. if (!Continuous)
  1277. return true;
  1278. if (!(AutoAttack || AutoFlee))
  1279. return true;
  1280. // Don't put anything in between the nilEvent and the ctlSelectEvent; these two
  1281. // run into each other!
  1282. case ctlSelectEvent:
  1283. if (eventP->data.ctlSelect.controlID >= EncounterTribble0Button &&
  1284. eventP->data.ctlSelect.controlID < EncounterTribble0Button + TRIBBLESONSCREEN)
  1285. {
  1286. if (AutoAttack || AutoFlee)
  1287. RedrawButtons = true;
  1288. AutoAttack = false;
  1289. AutoFlee = false;
  1290. if (RedrawButtons)
  1291. EncounterButtons();
  1292. FrmAlert( SqueekAlert );
  1293. handled = true;
  1294. break;
  1295. }
  1296. if (((eventP->eType == nilEvent) && AutoAttack) ||
  1297. (eventP->data.ctlSelect.controlID == EncounterAttackButton)) // Attack
  1298. {
  1299. if (AutoAttack || AutoFlee)
  1300. RedrawButtons = true;
  1301. AutoAttack = false;
  1302. AutoFlee = false;
  1303. if (RedrawButtons)
  1304. EncounterButtons();
  1305. if (TotalWeapons( &Ship, -1, -1 ) <= 0)
  1306. {
  1307. FrmAlert( NoWeaponsAlert );
  1308. return true;
  1309. }
  1310. if (EncounterType == POLICEINSPECTION && Ship.Cargo[FIREARMS] <= 0 &&
  1311. Ship.Cargo[NARCOTICS] <= 0)
  1312. {
  1313. if (FrmAlert( SureToFleeOrBribeAlert ) == SureToFleeOrBribeOKIwont)
  1314. return true;
  1315. }
  1316. if (ENCOUNTERPOLICE( EncounterType ) || EncounterType == POSTMARIEPOLICEENCOUNTER)
  1317. {
  1318. if (PoliceRecordScore > CRIMINALSCORE &&
  1319. FrmAlert( AttackByAccidentAlert ) == AttackByAccidentNo)
  1320. return true;
  1321. if (PoliceRecordScore > CRIMINALSCORE)
  1322. PoliceRecordScore = CRIMINALSCORE;
  1323. PoliceRecordScore += ATTACKPOLICESCORE;
  1324. if (EncounterType == POLICEIGNORE || EncounterType == POLICEINSPECTION ||
  1325. EncounterType == POSTMARIEPOLICEENCOUNTER)
  1326. {
  1327. EncounterType = POLICEATTACK;
  1328. }
  1329. }
  1330. else if (ENCOUNTERPIRATE( EncounterType ))
  1331. {
  1332. if (EncounterType == PIRATEIGNORE)
  1333. EncounterType = PIRATEATTACK;
  1334. }
  1335. else if (ENCOUNTERTRADER( EncounterType ))
  1336. {
  1337. if (EncounterType == TRADERIGNORE || EncounterType == TRADERBUY ||
  1338. EncounterType == TRADERSELL)
  1339. {
  1340. if (PoliceRecordScore >= CLEANSCORE)
  1341. {
  1342. if (FrmAlert( AttackTraderAlert ) == AttackTraderNo)
  1343. return true;
  1344. PoliceRecordScore = DUBIOUSSCORE;
  1345. }
  1346. else
  1347. PoliceRecordScore += ATTACKTRADERSCORE;
  1348. }
  1349. if (EncounterType != TRADERFLEE)
  1350. {
  1351. if (TotalWeapons( &Opponent, -1, -1 ) <= 0)
  1352. EncounterType = TRADERFLEE;
  1353. else if (GetRandom( ELITESCORE ) <= (ReputationScore * 10) / (1 + Opponent.Type))
  1354. EncounterType = TRADERFLEE;
  1355. else
  1356. EncounterType = TRADERATTACK;
  1357. }
  1358. }
  1359. else if (ENCOUNTERMONSTER( EncounterType ))
  1360. {
  1361. if (EncounterType == SPACEMONSTERIGNORE)
  1362. EncounterType = SPACEMONSTERATTACK;
  1363. }
  1364. else if (ENCOUNTERDRAGONFLY( EncounterType ))
  1365. {
  1366. if (EncounterType == DRAGONFLYIGNORE)
  1367. EncounterType = DRAGONFLYATTACK;
  1368. }
  1369. else if (ENCOUNTERSCARAB( EncounterType ))
  1370. {
  1371. if (EncounterType == SCARABIGNORE)
  1372. EncounterType = SCARABATTACK;
  1373. }
  1374. else if (ENCOUNTERFAMOUS( EncounterType ))
  1375. {
  1376. if (EncounterType != FAMOUSCAPATTACK &&
  1377. FrmAlert( SureToAttackFamousAlert ) == SureToAttackFamousOKIWont)
  1378. return true;
  1379. if (PoliceRecordScore > VILLAINSCORE)
  1380. PoliceRecordScore = VILLAINSCORE;
  1381. PoliceRecordScore += ATTACKTRADERSCORE;
  1382. if (EncounterType == CAPTAINHUIEENCOUNTER)
  1383. addNewsEvent(CAPTAINHUIEATTACKED);
  1384. else if (EncounterType == CAPTAINAHABENCOUNTER)
  1385. addNewsEvent(CAPTAINAHABATTACKED);
  1386. else if (EncounterType == CAPTAINCONRADENCOUNTER)
  1387. addNewsEvent(CAPTAINCONRADATTACKED);
  1388. EncounterType = FAMOUSCAPATTACK;
  1389. }
  1390. if (Continuous)
  1391. AutoAttack = true;
  1392. if (ExecuteAction( false ))
  1393. return true;
  1394. if (Ship.Hull <= 0)
  1395. return true;
  1396. }
  1397. else if (((eventP->eType == nilEvent) && AutoFlee) ||
  1398. (eventP->data.ctlSelect.controlID == EncounterFleeButton)) // Flee
  1399. {
  1400. if (AutoAttack || AutoFlee)
  1401. RedrawButtons = true;
  1402. AutoAttack = false;
  1403. AutoFlee = false;
  1404. if (RedrawButtons)
  1405. EncounterButtons();
  1406. if (EncounterType == POLICEINSPECTION && Ship.Cargo[FIREARMS] <= 0 &&
  1407. Ship.Cargo[NARCOTICS] <= 0 && WildStatus != 1 && (ReactorStatus == 0 || ReactorStatus == 21))
  1408. {
  1409. if (FrmAlert( SureToFleeOrBribeAlert ) == SureToFleeOrBribeOKIwont)
  1410. return true;
  1411. }
  1412. if (EncounterType == POLICEINSPECTION)
  1413. {
  1414. EncounterType = POLICEATTACK;
  1415. if (PoliceRecordScore > DUBIOUSSCORE)
  1416. PoliceRecordScore = DUBIOUSSCORE - (Difficulty < NORMAL ? 0 : 1);
  1417. else
  1418. PoliceRecordScore += FLEEFROMINSPECTION;
  1419. }
  1420. else if (EncounterType == POSTMARIEPOLICEENCOUNTER)
  1421. {
  1422. if (FrmAlert( SureToFleePostMarieAlert ) != SureToFleePostMarieOKIwont)
  1423. {
  1424. EncounterType = POLICEATTACK;
  1425. if (PoliceRecordScore >= CRIMINALSCORE)
  1426. PoliceRecordScore = CRIMINALSCORE;
  1427. else
  1428. PoliceRecordScore += ATTACKPOLICESCORE;
  1429. }
  1430. else
  1431. {
  1432. return true;
  1433. }
  1434. }
  1435. if (Continuous)
  1436. AutoFlee = true;
  1437. if (ExecuteAction( true ))
  1438. return true;
  1439. if (Ship.Hull <= 0)
  1440. return true;
  1441. }
  1442. else if (eventP->data.ctlSelect.controlID == EncounterIgnoreButton) // Ignore
  1443. {
  1444. // Only occurs when opponent either ignores you or flees, so just continue
  1445. if (AutoAttack || AutoFlee)
  1446. RedrawButtons = true;
  1447. AutoAttack = false;
  1448. AutoFlee = false;
  1449. if (RedrawButtons)
  1450. EncounterButtons();
  1451. }
  1452. else if (eventP->data.ctlSelect.controlID == EncounterTradeButton) // Trade in Orbit
  1453. {
  1454. if (EncounterType == TRADERBUY)
  1455. {
  1456. i = GetRandomTradeableItem (&Ship, TRADERBUY);
  1457. if (i == NARCOTICS || i == FIREARMS)
  1458. {
  1459. if (GetRandom(100) <= 45)
  1460. SellPrice[i] *= 0.8;
  1461. else
  1462. SellPrice[i] *= 1.1;
  1463. }
  1464. else
  1465. {
  1466. if (GetRandom(100) <= 10)
  1467. SellPrice[i] *= 0.9;
  1468. else
  1469. SellPrice[i] *= 1.1;
  1470. }
  1471. SellPrice[i] /= Tradeitem[i].RoundOff;
  1472. ++SellPrice[i];
  1473. SellPrice[i] *= Tradeitem[i].RoundOff;
  1474. if (SellPrice[i] < Tradeitem[i].MinTradePrice)
  1475. SellPrice[i] = Tradeitem[i].MinTradePrice;
  1476. if (SellPrice[i] > Tradeitem[i].MaxTradePrice)
  1477. SellPrice[i] = Tradeitem[i].MaxTradePrice;
  1478. frm = FrmInitForm( TradeInOrbitForm );
  1479. StrCopy( SBuf, "The trader wants to buy ");
  1480. StrCat ( SBuf, Tradeitem[i].Name);
  1481. StrCat ( SBuf, ",");
  1482. setLabelText( frm, TradeInOrbitDealLabel, SBuf );
  1483. StrCopy( SBuf, "and offers ");
  1484. StrIToA( SBuf2, SellPrice[i]);
  1485. StrCat ( SBuf, SBuf2);
  1486. StrCat ( SBuf, " cr. each.");
  1487. setLabelText( frm, TradeInOrbitNumberItemsLabel, SBuf);
  1488. StrCopy ( SBuf, "You have ");
  1489. StrIToA ( SBuf2, Ship.Cargo[i]);
  1490. StrCat ( SBuf, SBuf2);
  1491. if (Ship.Cargo[i] > 1)
  1492. StrCat ( SBuf, " units");
  1493. else
  1494. StrCat (SBuf, " unit");
  1495. StrCat( SBuf, " available.");
  1496. setLabelText( frm, TradeInOrbitQuantityAvailableLabel, SBuf );
  1497. StrCopy( SBuf, "You paid about " );
  1498. StrIToA( SBuf2, BuyingPrice[i] / Ship.Cargo[i] );
  1499. StrCat( SBuf, SBuf2 );
  1500. StrCat( SBuf, " cr. per unit." );
  1501. setLabelText( frm, TradeInOrbitAveragePriceLabel, SBuf );
  1502. setLabelText( frm, TradeInOrbitHowManyLabel, "How many do you wish to sell?");
  1503. QuantityH = (Handle) SetField( frm, TradeInOrbitQuantityField, "", 5, true );
  1504. d = FrmDoDialog(frm);
  1505. j = 0;
  1506. if (d == TradeInOrbitOKButton)
  1507. {
  1508. GetField( frm, TradeInOrbitQuantityField, SBuf, QuantityH );
  1509. if (SBuf[0] != '\0')
  1510. {
  1511. j = max(0, min(Ship.Cargo[i], StrAToI(SBuf)));
  1512. }
  1513. }
  1514. else if (d == TradeInOrbitAllButton)
  1515. {
  1516. j = Ship.Cargo[i];
  1517. }
  1518. j = min( j, Shiptype[Opponent.Type].CargoBays );
  1519. if (j > 0)
  1520. {
  1521. BuyingPrice[i] = BuyingPrice[i]*(Ship.Cargo[i]-j)/Ship.Cargo[i];
  1522. Ship.Cargo[i] -= j;
  1523. Opponent.Cargo[i] = j;
  1524. Credits += j * SellPrice[i];
  1525. FrmCustomAlert(OrbitTradeCompletedAlert,"Thanks for selling us the", Tradeitem[i].Name, " ");
  1526. }
  1527. FrmDeleteForm( frm );
  1528. }
  1529. else if (EncounterType == TRADERSELL)
  1530. {
  1531. i = GetRandomTradeableItem (&Opponent, TRADERSELL);
  1532. if (i == NARCOTICS || i == FIREARMS)
  1533. {
  1534. if (GetRandom(100) <= 45)
  1535. BuyPrice[i] *= 1.1;
  1536. else
  1537. BuyPrice[i] *= 0.8;
  1538. }
  1539. else
  1540. {
  1541. if (GetRandom(100) <= 10)
  1542. BuyPrice[i] *= 1.1;
  1543. else
  1544. BuyPrice[i] *= 0.9;
  1545. }
  1546. BuyPrice[i] /= Tradeitem[i].RoundOff;
  1547. BuyPrice[i] *= Tradeitem[i].RoundOff;
  1548. if (BuyPrice[i] < Tradeitem[i].MinTradePrice)
  1549. BuyPrice[i] = Tradeitem[i].MinTradePrice;
  1550. if (BuyPrice[i] > Tradeitem[i].MaxTradePrice)
  1551. BuyPrice[i] = Tradeitem[i].MaxTradePrice;
  1552. frm = FrmInitForm( TradeInOrbitForm );
  1553. StrCopy( SBuf, "The trader wants to sell ");
  1554. StrCat ( SBuf, Tradeitem[i].Name);
  1555. setLabelText( frm, TradeInOrbitDealLabel, SBuf );
  1556. StrCopy( SBuf, "for the price of ");
  1557. StrIToA( SBuf2, BuyPrice[i]);
  1558. StrCat ( SBuf, SBuf2);
  1559. StrCat ( SBuf, " cr. each.");
  1560. setLabelText( frm, TradeInOrbitNumberItemsLabel, SBuf);
  1561. StrCopy ( SBuf, "The trader has ");
  1562. StrIToA ( SBuf2, Opponent.Cargo[i]);
  1563. StrCat ( SBuf, SBuf2);
  1564. if (Opponent.Cargo[i] > 1)
  1565. StrCat ( SBuf, " units");
  1566. else
  1567. StrCat (SBuf, " unit");
  1568. StrCat ( SBuf, " for sale.");
  1569. setLabelText( frm, TradeInOrbitQuantityAvailableLabel, SBuf );
  1570. StrCopy( SBuf, "You can afford " );
  1571. StrIToA( SBuf2, Credits / BuyPrice[i] );
  1572. StrCat( SBuf, SBuf2 );
  1573. if (Credits/BuyPrice[i] > 1)
  1574. StrCat( SBuf, " units." );
  1575. else
  1576. StrCat( SBuf, " unit.");
  1577. setLabelText( frm, TradeInOrbitAveragePriceLabel, SBuf );
  1578. setLabelText( frm, TradeInOrbitHowManyLabel, "How many do you wish to buy?");
  1579. QuantityH = (Handle) SetField( frm, TradeInOrbitQuantityField, "", 5, true );
  1580. d = FrmDoDialog(frm);
  1581. j = 0;
  1582. if (d == TradeInOrbitOKButton)
  1583. {
  1584. GetField( frm, TradeInOrbitQuantityField, SBuf, QuantityH );
  1585. if (SBuf[0] != '\0')
  1586. {
  1587. j = max(0, min(Opponent.Cargo[i], StrAToI(SBuf)));;
  1588. }
  1589. }
  1590. else if (d == TradeInOrbitAllButton)
  1591. {
  1592. j = min(Opponent.Cargo[i], (TotalCargoBays()-FilledCargoBays()));
  1593. }
  1594. j = min ( j, (Credits / BuyPrice[i]));
  1595. if (j > 0)
  1596. {
  1597. Ship.Cargo[i] += j;
  1598. Opponent.Cargo[i] -= j;
  1599. BuyingPrice[i] += (j * BuyPrice[i]);
  1600. Credits -= (j * BuyPrice[i]);
  1601. FrmCustomAlert(OrbitTradeCompletedAlert,"Thanks for buying the", Tradeitem[i].Name, " ");
  1602. }
  1603. FrmDeleteForm( frm );
  1604. }
  1605. }
  1606. else if (eventP->data.ctlSelect.controlID == EncounterYieldButton) // Yield Narcotics from Marie Celeste
  1607. {
  1608. if (WildStatus == 1)
  1609. {
  1610. if (FrmCustomAlert( WantToSurrenderAlert, "You have Jonathan Wild on board! ", "Wild will be arrested, too. ", NULL ) == WantToSurrenderNo)
  1611. return true;
  1612. }
  1613. else if (ReactorStatus > 0 && ReactorStatus < 21)
  1614. {
  1615. if (FrmCustomAlert( WantToSurrenderAlert, "You have an illegal Reactor on board! ", "They will destroy the reactor. ", NULL) == WantToSurrenderNo)
  1616. return true;
  1617. }
  1618. if (WildStatus == 1 || (ReactorStatus > 0 && ReactorStatus < 21))
  1619. {
  1620. Arrested();
  1621. }
  1622. else
  1623. {
  1624. // Police Record becomes dubious, if it wasn't already.
  1625. if (PoliceRecordScore > DUBIOUSSCORE)
  1626. PoliceRecordScore = DUBIOUSSCORE;
  1627. Ship.Cargo[NARCOTICS]=0;
  1628. Ship.Cargo[FIREARMS]=0;
  1629. FrmAlert(YieldNarcoticsAlert);
  1630. }
  1631. }
  1632. else if (eventP->data.ctlSelect.controlID == EncounterSurrenderButton) // Surrender
  1633. {
  1634. if (AutoAttack || AutoFlee)
  1635. RedrawButtons = true;
  1636. AutoAttack = false;
  1637. AutoFlee = false;
  1638. if (RedrawButtons)
  1639. EncounterButtons();
  1640. if (Opponent.Type == MANTISTYPE)
  1641. {
  1642. if (ArtifactOnBoard)
  1643. {
  1644. if (FrmAlert( WantToSurrenderToAliensAlert ) == WantToSurrenderToAliensNo)
  1645. return true;
  1646. else
  1647. {
  1648. FrmAlert( ArtifactStolenAlert );
  1649. ArtifactOnBoard = 0;
  1650. }
  1651. }
  1652. else
  1653. {
  1654. FrmAlert( NoSurrenderAlert );
  1655. return true;
  1656. }
  1657. }
  1658. else if (ENCOUNTERPOLICE( EncounterType ))
  1659. {
  1660. if (PoliceRecordScore <= PSYCHOPATHSCORE)
  1661. {
  1662. FrmAlert( NoSurrenderAlert );
  1663. return true;
  1664. }
  1665. else
  1666. {
  1667. if (WildStatus == 1)
  1668. {
  1669. if (FrmCustomAlert( WantToSurrenderAlert, "You have Jonathan Wild on board! ", "Wild will be arrested, too. ", NULL ) == WantToSurrenderNo)
  1670. return true;
  1671. }
  1672. else if (ReactorStatus > 0 && ReactorStatus < 21)
  1673. {
  1674. if (FrmCustomAlert( WantToSurrenderAlert, "You have an illegal Reactor on board! ", "They will destroy the reactor. ", NULL) == WantToSurrenderNo)
  1675. return true;
  1676. }
  1677. else
  1678. {
  1679. if (FrmCustomAlert( WantToSurrenderAlert, NULL, NULL, NULL ) == WantToSurrenderNo)
  1680. return true;
  1681. }
  1682. Arrested();
  1683. return true;
  1684. }
  1685. }
  1686. else
  1687. {
  1688. Raided = true;
  1689. TotalCargo = 0;
  1690. for (i=0; i<MAXTRADEITEM; ++i)
  1691. TotalCargo += Ship.Cargo[i];
  1692. if (TotalCargo <= 0)
  1693. {
  1694. Blackmail = min( 25000, max( 500, CurrentWorth() / 20 ) );
  1695. FrmAlert( PiratesFindNoCargoAlert );
  1696. if (Credits >= Blackmail)
  1697. Credits -= Blackmail;
  1698. else
  1699. {
  1700. Debt += (Blackmail - Credits);
  1701. Credits = 0;
  1702. }
  1703. }
  1704. else
  1705. {
  1706. FrmAlert( PiratesPlunderAlert );
  1707. Bays = Shiptype[Opponent.Type].CargoBays;
  1708. for (i=0; i<MAXGADGET; ++i)
  1709. if (Opponent.Gadget[i] == EXTRABAYS)
  1710. Bays += 5;
  1711. for (i=0; i<MAXTRADEITEM; ++i)
  1712. Bays -= Opponent.Cargo[i];
  1713. // Pirates steal everything
  1714. if (Bays >= TotalCargo)
  1715. {
  1716. for (i=0; i<MAXTRADEITEM; ++i)
  1717. {
  1718. Ship.Cargo[i] = 0;
  1719. BuyingPrice[i] = 0;
  1720. }
  1721. }
  1722. else
  1723. {
  1724. // Pirates steal a lot
  1725. while (Bays > 0)
  1726. {
  1727. i = GetRandom( MAXTRADEITEM );
  1728. if (Ship.Cargo[i] > 0)
  1729. {
  1730. BuyingPrice[i] = (BuyingPrice[i] * (Ship.Cargo[i] - 1)) / Ship.Cargo[i];
  1731. --Ship.Cargo[i];
  1732. --Bays;
  1733. }
  1734. }
  1735. }
  1736. }
  1737. if ((WildStatus == 1) && (Shiptype[Opponent.Type].CrewQuarters > 1))
  1738. {
  1739. // Wild hops onto Pirate Ship
  1740. WildStatus = 0;
  1741. FrmAlert( WildGoesWithPiratesAlert );
  1742. }
  1743. else if (WildStatus == 1)
  1744. {
  1745. // no room on pirate ship
  1746. FrmAlert( WildStaysAboardAlert );
  1747. }
  1748. if (ReactorStatus > 0 && ReactorStatus < 21)
  1749. {
  1750. // pirates puzzled by reactor
  1751. FrmAlert( PiratesDontStealReactorAlert );
  1752. }
  1753. }
  1754. }
  1755. else if (eventP->data.ctlSelect.controlID == EncounterBribeButton) // Bribe
  1756. {
  1757. if (AutoAttack || AutoFlee)
  1758. RedrawButtons = true;
  1759. AutoAttack = false;
  1760. AutoFlee = false;
  1761. if (RedrawButtons)
  1762. EncounterButtons();
  1763. if (Politics[SolarSystem[WarpSystem].Politics].BribeLevel <= 0)
  1764. {
  1765. FrmAlert( CantBeBribedAlert );
  1766. return true;
  1767. }
  1768. if (EncounterType == POSTMARIEPOLICEENCOUNTER)
  1769. {
  1770. FrmAlert( MarieCantBeBribedAlert );
  1771. return true;
  1772. }
  1773. if (EncounterType == POLICEINSPECTION && Ship.Cargo[FIREARMS] <= 0 &&
  1774. Ship.Cargo[NARCOTICS] <= 0 && WildStatus != 1)
  1775. {
  1776. if (FrmAlert( SureToFleeOrBribeAlert ) == SureToFleeOrBribeOKIwont)
  1777. return true;
  1778. }
  1779. // Bribe depends on how easy it is to bribe the police and commander's current worth
  1780. Bribe = CurrentWorth() /
  1781. ((10L + 5L * (IMPOSSIBLE - Difficulty)) * Politics[SolarSystem[WarpSystem].Politics].BribeLevel);
  1782. if (Bribe % 100 != 0)
  1783. Bribe += (100 - (Bribe % 100));
  1784. if (WildStatus == 1 || (ReactorStatus > 0 && ReactorStatus < 21))
  1785. {
  1786. if (Difficulty <= NORMAL)
  1787. Bribe *= 2;
  1788. else
  1789. Bribe *= 3;
  1790. }
  1791. Bribe = max( 100, min( Bribe, 10000 ) );
  1792. frmP = FrmInitForm( BribeForm );
  1793. StrCopy( SBuf, "of " );
  1794. StrIToA( SBuf2, Bribe );
  1795. StrCat( SBuf, SBuf2 );
  1796. StrCat( SBuf, " credits." );
  1797. setLabelText( frmP, BribeBribeLabel, SBuf );
  1798. d = FrmDoDialog( frmP );
  1799. FrmDeleteForm( frmP );
  1800. if (d == BribeOfferBribeButton)
  1801. {
  1802. if (Credits < Bribe)
  1803. {
  1804. FrmAlert( NoMoneyForBribeAlert );
  1805. return true;
  1806. }
  1807. Credits -= Bribe;
  1808. }
  1809. else
  1810. return true;
  1811. }
  1812. else if (eventP->data.ctlSelect.controlID == EncounterSubmitButton) // Submit
  1813. {
  1814. if (AutoAttack || AutoFlee)
  1815. RedrawButtons = true;
  1816. AutoAttack = false;
  1817. AutoFlee = false;
  1818. if (RedrawButtons)
  1819. EncounterButtons();
  1820. if (EncounterType == POLICEINSPECTION && (Ship.Cargo[FIREARMS] > 0 ||
  1821. Ship.Cargo[NARCOTICS] > 0 || WildStatus == 1 ||
  1822. (ReactorStatus > 1 && ReactorStatus < 21)))
  1823. {
  1824. if (WildStatus == 1)
  1825. {
  1826. if (Ship.Cargo[FIREARMS] > 0 || Ship.Cargo[NARCOTICS] > 0)
  1827. {
  1828. StrCopy( SBuf, "Jonathan Wild and illegal goods");
  1829. }
  1830. else
  1831. {
  1832. StrCopy( SBuf, "Jonathan Wild");
  1833. }
  1834. StrCopy(SBuf2, "You will be arrested!");
  1835. }
  1836. else if (ReactorStatus > 0 && ReactorStatus < 21)
  1837. {
  1838. if (Ship.Cargo[FIREARMS] > 0 || Ship.Cargo[NARCOTICS] > 0)
  1839. {
  1840. StrCopy( SBuf, "an illegal Ion Reactor and other illegal goods");
  1841. }
  1842. else
  1843. {
  1844. StrCopy( SBuf, "an illegal Ion Reactor");
  1845. }
  1846. StrCopy(SBuf2, "You will be arrested!");
  1847. }
  1848. else
  1849. {
  1850. StrCopy( SBuf, "illegal goods");
  1851. StrCopy( SBuf2, " ");
  1852. }
  1853. if (FrmCustomAlert( SureToSubmitAlert, SBuf, SBuf2, NULL ) == SureToSubmitNo)
  1854. return true;
  1855. }
  1856. if ((Ship.Cargo[FIREARMS] > 0) || (Ship.Cargo[NARCOTICS] > 0))
  1857. {
  1858. // If you carry illegal goods, they are impounded and you are fined
  1859. Ship.Cargo[FIREARMS] = 0;
  1860. BuyingPrice[FIREARMS] = 0;
  1861. Ship.Cargo[NARCOTICS] = 0;
  1862. BuyingPrice[NARCOTICS] = 0;
  1863. Fine = CurrentWorth() / ((IMPOSSIBLE+2-Difficulty) * 10L);
  1864. if (Fine % 50 != 0)
  1865. Fine += (50 - (Fine % 50));
  1866. Fine = max( 100, min( Fine, 10000 ) );
  1867. if (Credits >= Fine)
  1868. Credits -= Fine;
  1869. else
  1870. {
  1871. Debt += (Fine - Credits);
  1872. Credits = 0;
  1873. }
  1874. frmP = FrmInitForm( IllegalGoodsForm );
  1875. StrIToA( SBuf, Fine );
  1876. StrCat( SBuf, " credits." );
  1877. setLabelText( frmP, IllegalGoodsFineLabel, SBuf );
  1878. FrmDoDialog( frmP );
  1879. FrmDeleteForm( frmP );
  1880. PoliceRecordScore += TRAFFICKING;
  1881. }
  1882. else if (WildStatus != 1)
  1883. {
  1884. // If you aren't carrying illegal goods, the police will increase your lawfulness record
  1885. FrmAlert( NoIllegalGoodsAlert );
  1886. PoliceRecordScore -= TRAFFICKING;
  1887. }
  1888. if (WildStatus == 1)
  1889. {
  1890. // Jonathan Wild Captured, and your status damaged.
  1891. Arrested();
  1892. return true;
  1893. }
  1894. if (ReactorStatus > 0 && ReactorStatus < 21)
  1895. {
  1896. // Police confiscate the Reactor.
  1897. // Of course, this can only happen if somehow your
  1898. // Police Score gets repaired while you have the
  1899. // reactor on board -- otherwise you'll be arrested
  1900. // before we get to this point. (no longer true - 25 August 2002)
  1901. FrmAlert( PoliceConfiscateReactorAlert );
  1902. ReactorStatus = 0;
  1903. }
  1904. }
  1905. else if (eventP->data.ctlSelect.controlID == EncounterPlunderButton) // Plunder
  1906. {
  1907. if (AutoAttack || AutoFlee)
  1908. RedrawButtons = true;
  1909. AutoAttack = false;
  1910. AutoFlee = false;
  1911. if (RedrawButtons)
  1912. EncounterButtons();
  1913. if (ENCOUNTERTRADER( EncounterType ))
  1914. PoliceRecordScore += PLUNDERTRADERSCORE;
  1915. else
  1916. PoliceRecordScore += PLUNDERPIRATESCORE;
  1917. CurForm = PlunderForm;
  1918. FrmGotoForm( CurForm );
  1919. return true;
  1920. }
  1921. else if (eventP->data.ctlSelect.controlID == EncounterInterruptButton) // Interrupt automatic attack/flight
  1922. {
  1923. if (AutoAttack || AutoFlee)
  1924. RedrawButtons = true;
  1925. AutoAttack = false;
  1926. AutoFlee = false;
  1927. if (RedrawButtons)
  1928. EncounterButtons();
  1929. return true;
  1930. }
  1931. else if (eventP->data.ctlSelect.controlID == EncounterMeetButton) // Meet with Famous Captain
  1932. {
  1933. if (EncounterType == CAPTAINAHABENCOUNTER)
  1934. {
  1935. // Trade a reflective shield for skill points in piloting?
  1936. if (FrmAlert( EngageCaptainAhabAlert) == EngageCaptainAhabYesTradeShield)
  1937. {
  1938. // remove the last reflective shield
  1939. i=MAXSHIELD - 1;
  1940. while (i >= 0)
  1941. {
  1942. if (Ship.Shield[i] == REFLECTIVESHIELD)
  1943. {
  1944. for (m=i+1; m<MAXSHIELD; ++m)
  1945. {
  1946. Ship.Shield[m-1] = Ship.Shield[m];
  1947. Ship.ShieldStrength[m-1] = Ship.ShieldStrength[m];
  1948. }
  1949. Ship.Shield[MAXSHIELD-1] = -1;
  1950. Ship.ShieldStrength[MAXSHIELD-1] = 0;
  1951. i = -1;
  1952. }
  1953. i--;
  1954. }
  1955. // add points to piloting skill
  1956. // two points if you're on beginner-normal, one otherwise
  1957. if (Difficulty < HARD)
  1958. COMMANDER.Pilot += 2;
  1959. else
  1960. COMMANDER.Pilot += 1;
  1961. if (COMMANDER.Pilot > MAXSKILL)
  1962. {
  1963. COMMANDER.Pilot = MAXSKILL;
  1964. }
  1965. FrmAlert( TrainingCompletedAlert );
  1966. }
  1967. }
  1968. else if (EncounterType == CAPTAINCONRADENCOUNTER)
  1969. {
  1970. // Trade a military laser for skill points in engineering?
  1971. if (FrmAlert( EngageCaptainConradAlert) == EngageCaptainConradYesTradeLaser)
  1972. {
  1973. // remove the last military laser
  1974. i=MAXWEAPON - 1;
  1975. while (i>=0)
  1976. {
  1977. if (Ship.Weapon[i] == MILITARYLASERWEAPON)
  1978. {
  1979. for (m=i+1; m<MAXWEAPON; ++m)
  1980. {
  1981. Ship.Weapon[m-1] = Ship.Weapon[m];
  1982. }
  1983. Ship.Weapon[MAXWEAPON-1] = -1;
  1984. i = -1;
  1985. }
  1986. i--;
  1987. }
  1988. // add points to engineering skill
  1989. // two points if you're on beginner-normal, one otherwise
  1990. if (Difficulty < HARD)
  1991. COMMANDER.Engineer += 2;
  1992. else
  1993. COMMANDER.Engineer += 1;
  1994. if (COMMANDER.Engineer > MAXSKILL)
  1995. {
  1996. COMMANDER.Engineer = MAXSKILL;
  1997. }
  1998. FrmAlert( TrainingCompletedAlert );
  1999. }
  2000. }
  2001. else if (EncounterType == CAPTAINHUIEENCOUNTER)
  2002. {
  2003. // Trade a military laser for skill points in trading?
  2004. if (FrmAlert( EngageCaptainHuieAlert) == EngageCaptainHuieYesTradeLaser)
  2005. {
  2006. // remove the last military laser
  2007. i=MAXWEAPON - 1;
  2008. while (i>=0)
  2009. {
  2010. if (Ship.Weapon[i] == MILITARYLASERWEAPON)
  2011. {
  2012. for (m=i+1; m<MAXWEAPON; ++m)
  2013. {
  2014. Ship.Weapon[m-1] = Ship.Weapon[m];
  2015. }
  2016. Ship.Weapon[MAXWEAPON-1] = -1;
  2017. i = -1;
  2018. }
  2019. i--;
  2020. }
  2021. // add points to trading skill
  2022. // two points if you're on beginner-normal, one otherwise
  2023. if (Difficulty < HARD)
  2024. COMMANDER.Trader += 2;
  2025. else
  2026. COMMANDER.Trader += 1;
  2027. if (COMMANDER.Trader > MAXSKILL)
  2028. {
  2029. COMMANDER.Trader = MAXSKILL;
  2030. }
  2031. RecalculateBuyPrices(COMMANDER.CurSystem);
  2032. FrmAlert( TrainingCompletedAlert );
  2033. }
  2034. }
  2035. }
  2036. else if (eventP->data.ctlSelect.controlID == EncounterBoardButton) // Board Marie Celeste
  2037. {
  2038. if (EncounterType == MARIECELESTEENCOUNTER)
  2039. {
  2040. // take the cargo of the Marie Celeste?
  2041. if (FrmAlert( EngageMarieAlert ) == EngageMarieYesTakeCargo)
  2042. {
  2043. CurForm = PlunderForm;
  2044. FrmGotoForm( CurForm );
  2045. return true;
  2046. }
  2047. }
  2048. }
  2049. else if (eventP->data.ctlSelect.controlID == EncounterDrinkButton) // Drink Tonic?
  2050. {
  2051. if (EncounterType == BOTTLEGOODENCOUNTER)
  2052. {
  2053. // Quaff the good bottle of Skill Tonic?
  2054. if (FrmAlert( EngageBottleAlert ) == EngageBottleYesDrinkIt)
  2055. {
  2056. // two points if you're on beginner-normal, one otherwise
  2057. IncreaseRandomSkill();
  2058. if (Difficulty < HARD)
  2059. IncreaseRandomSkill();
  2060. FrmAlert( GoodDrinkAlert );
  2061. }
  2062. }
  2063. else if (EncounterType == BOTTLEOLDENCOUNTER)
  2064. {
  2065. // Quaff the out of date bottle of Skill Tonic?
  2066. if (FrmAlert( EngageBottleAlert ) == EngageBottleYesDrinkIt)
  2067. {
  2068. TonicTweakRandomSkill();
  2069. FrmAlert( StrangeDrinkAlert );
  2070. }
  2071. }
  2072. }
  2073. Travel();
  2074. handled = true;
  2075. break;
  2076. default:
  2077. break;
  2078. }
  2079. return handled;
  2080. }