OPOWER.cpp 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257
  1. /*
  2. * Seven Kingdoms: Ancient Adversaries
  3. *
  4. * Copyright 1997,1998 Enlight Software Ltd.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. //Filename : OPOWER.CPP
  21. //Description : Object Power
  22. #include <OMOUSE.h>
  23. #include <OMOUSECR.h>
  24. #include <OUNIT.h>
  25. #include <OFIRM.h>
  26. #include <OTOWN.h>
  27. #include <OSITE.h>
  28. #include <OSYS.h>
  29. #include <ONATION.h>
  30. #include <OBOX.h>
  31. #include <OIMGRES.h>
  32. #include <OMOUSECR.h>
  33. #include <OWORLD.h>
  34. #include <OINFO.h>
  35. #include <OU_CARA.h>
  36. #include <OU_MARI.h>
  37. #include <OPOWER.h>
  38. #include <OWALLRES.h>
  39. #include <OSERES.h>
  40. #include <OREMOTE.h>
  41. //-------------- Define constant -----------------//
  42. #define DETECT_SPREAD 3
  43. static short nation_divide_order[MAX_NATION+1] = {1, 2, 3, 4, 5, 6, 7, 0};
  44. //-------- Begin of static function divide_by_nation --------//
  45. static void divide_by_nation(short *nationUnitCount, short *selectedArray, int selectedCount)
  46. {
  47. short *orderedArray = (short*) mem_add(sizeof(short)*selectedCount);
  48. short *nationOrderPtr = nation_divide_order;
  49. short unitCount = 0;
  50. short *selectedUnitPtr;
  51. Unit *unitPtr;
  52. int i, j;
  53. for(i=0; i<=MAX_NATION; ++i, nationOrderPtr++)
  54. {
  55. for(j=0, selectedUnitPtr=selectedArray; j<selectedCount; ++j, selectedUnitPtr++)
  56. {
  57. err_when(unit_array.is_deleted(*selectedUnitPtr));
  58. unitPtr = unit_array[*selectedUnitPtr];
  59. if(unitPtr->nation_recno == *nationOrderPtr)
  60. orderedArray[unitCount++] = *selectedUnitPtr;
  61. }
  62. err_when(unitCount>selectedCount);
  63. nationUnitCount[i] = unitCount;
  64. if(i<MAX_NATION && unitCount==selectedCount)
  65. {
  66. for(int k=i+1; k<=MAX_NATION; ++k)
  67. nationUnitCount[k] = selectedCount;
  68. break;
  69. }
  70. }
  71. memcpy(selectedArray, orderedArray, sizeof(short) * selectedCount);
  72. mem_del(orderedArray);
  73. orderedArray = NULL;
  74. }
  75. //--------- End of static function divide_by_nation ---------//
  76. //----------- Begin of function Power::Power -----------//
  77. Power::Power()
  78. {
  79. memset( this, 0, sizeof(Power) );
  80. }
  81. //----------- End of function Power::Power -----------//
  82. //----------- Begin of function Power::~Power -----------//
  83. Power::~Power()
  84. {
  85. }
  86. //----------- End of function Power::~Power -----------//
  87. //----------- Begin of function Power::init -----------//
  88. void Power::init()
  89. {
  90. memset( this, 0, sizeof(Power) );
  91. reset_selection(); // there may be selections left by the previous game.
  92. }
  93. //----------- End of function Power::init -----------//
  94. //-------- Begin of function Power::mouse_handler --------//
  95. //
  96. // React immediately when the mouse is moved or clicked.
  97. //
  98. void Power::mouse_handler()
  99. {
  100. if( sys.view_mode != MODE_NORMAL )
  101. {
  102. mouse_cursor.set_icon(CURSOR_NORMAL);
  103. return;
  104. }
  105. if( !enable_flag || win_opened || Box::opened_flag ||
  106. sys.signal_exit_flag ) // a window or box is opened upon the current interface
  107. {
  108. return;
  109. }
  110. //---- if there is an object at where the mouse cursor is pointing at, change the cursor shape ----//
  111. Location *pointingLoc;
  112. short selectedRecno = 0;
  113. ScreenObjectType selectedType = find_selected_type(&selectedRecno);
  114. if( mouse.cur_x >= ZOOM_X1 && mouse.cur_x <= ZOOM_X2 &&
  115. mouse.cur_y >= ZOOM_Y1 && mouse.cur_y <= ZOOM_Y2 &&
  116. (pointingLoc = test_detect(mouse.cur_x, mouse.cur_y))!= NULL)
  117. {
  118. // ------- pointing something -------//
  119. short pointingRecno;
  120. ScreenObjectType pointingType = find_pointing_type(pointingLoc, &pointingRecno);
  121. mouse_cursor.set_icon( choose_cursor(mouse.cur_x, mouse.cur_y,
  122. selectedType, selectedRecno, pointingType, pointingRecno) );
  123. }
  124. else
  125. mouse_cursor.set_icon( choose_cursor(mouse.cur_x, mouse.cur_y,
  126. selectedType, selectedRecno, SCREEN_OBJECT_NONE, 0) );
  127. //---- pressing right button in command mode -> cancel command mode ----//
  128. if( mouse.right_press && command_id )
  129. {
  130. command_id = 0;
  131. info.disp();
  132. return;
  133. }
  134. /*
  135. //------ detect selecting objects and laying tracks ------//
  136. if( detect_frame() )
  137. return;
  138. //----- detect right mouse button to select defined unit groups -----//
  139. int shiftPressed = GetKeyState(VK_SHIFT) & 0X0100; // return the current real-time key state
  140. if( mouse.right_press && !shiftPressed ) // shift key to override the standard selection action and go for attacking own units
  141. {
  142. if( mouse.cur_x >= ZOOM_X1 && mouse.cur_x <= ZOOM_X2 && // if the mouse is inside the zoom area
  143. mouse.cur_y >= ZOOM_Y1 && mouse.cur_y <= ZOOM_Y2 )
  144. {
  145. if( detect_select( mouse.cur_x, mouse.cur_y,
  146. mouse.cur_x, mouse.cur_y, 1 ) ) // 1-recall group
  147. {
  148. return;
  149. }
  150. }
  151. }
  152. //----------- detect action ------------//
  153. // ##### begin Gilbert 29/5 ########//
  154. if( detect_action() && unit_array.selected_recno )
  155. {
  156. if( se_res.mark_command_time() )
  157. {
  158. Unit *unitPtr = unit_array[unit_array.selected_recno];
  159. se_res.far_sound( unitPtr->cur_x_loc(), unitPtr->cur_y_loc(), 1, 'S',
  160. unitPtr->sprite_id, "ACK");
  161. }
  162. }
  163. // ##### end Gilbert 29/5 ########//
  164. */
  165. }
  166. //--------- End of function Power::mouse_handler ---------//
  167. //-------- Begin of function Power::detect_frame --------//
  168. //
  169. // Detect selecting objects or laying tracks with the mouse
  170. // selection frame.
  171. //
  172. // return: <int> 1 - objects selected or tracks built.
  173. // 0 - nothing selected or built.
  174. //
  175. int Power::detect_frame()
  176. {
  177. //----- detect left mouse button to activate frame selection -----//
  178. int rc=0, selectedCount=0;
  179. Location* locPtr;
  180. if( mouse.is_mouse_event() )
  181. {
  182. if( mouse.mouse_event_type == LEFT_BUTTON )
  183. {
  184. int mouseX = mouse.click_x(LEFT_BUTTON);
  185. int mouseY = mouse.click_y(LEFT_BUTTON);
  186. if( !mouse_cursor.frame_flag )
  187. {
  188. if( mouseX >= ZOOM_X1 && mouseX <= ZOOM_X2 && // if the mouse is inside the zoom area
  189. mouseY >= ZOOM_Y1 && mouseY <= ZOOM_Y2 )
  190. {
  191. int curXLoc = world.zoom_matrix->top_x_loc + (mouseX-ZOOM_X1)/ZOOM_LOC_WIDTH;
  192. int curYLoc = world.zoom_matrix->top_y_loc + (mouseY-ZOOM_Y1)/ZOOM_LOC_HEIGHT;
  193. locPtr = world.get_loc(curXLoc, curYLoc);
  194. //-------- set boundary of mouse -------//
  195. mouse.set_boundary(ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2);
  196. //------- activate frame selection --------//
  197. switch(command_id)
  198. {
  199. case COMMAND_BUILD_FIRM:
  200. if(!unit_array.is_deleted(command_unit_recno) && unit_array[command_unit_recno]->is_visible())
  201. {
  202. Unit *cmdUnit = unit_array[command_unit_recno];
  203. if( se_res.mark_command_time() )
  204. {
  205. se_res.far_sound( cmdUnit->cur_x_loc(), cmdUnit->cur_y_loc(), 1,
  206. 'S', cmdUnit->sprite_id, "ACK" );
  207. }
  208. cmdUnit->build_firm(curXLoc, curYLoc, command_para, COMMAND_PLAYER);
  209. }
  210. command_id = 0;
  211. rc = 1;
  212. info.disp();
  213. break;
  214. case COMMAND_BURN:
  215. if(!unit_array.is_deleted(command_unit_recno) && unit_array[command_unit_recno]->is_visible())
  216. {
  217. Unit *cmdUnit = unit_array[command_unit_recno];
  218. if( se_res.mark_command_time() )
  219. {
  220. se_res.far_sound( cmdUnit->cur_x_loc(), cmdUnit->cur_y_loc(), 1,
  221. 'S', cmdUnit->sprite_id, "ACK" );
  222. }
  223. cmdUnit->burn(curXLoc, curYLoc, COMMAND_PLAYER);
  224. }
  225. command_id = 0;
  226. rc = 1;
  227. break;
  228. case COMMAND_SETTLE:
  229. if( se_res.mark_command_time() )
  230. {
  231. Unit *repUnit = unit_array[unit_array.selected_recno];
  232. se_res.far_sound( repUnit->cur_x_loc(), repUnit->cur_y_loc(), 1,
  233. 'S', repUnit->sprite_id, "ACK");
  234. }
  235. if( locPtr->is_town() && town_array[locPtr->town_recno()]->nation_recno == unit_array[unit_array.selected_recno]->nation_recno )
  236. {
  237. Town *townPtr = town_array[locPtr->town_recno()];
  238. unit_array.assign(townPtr->loc_x1, townPtr->loc_y1, 0, COMMAND_PLAYER ); // assign to an existing town
  239. }
  240. else
  241. unit_array.settle(curXLoc, curYLoc, 0, COMMAND_PLAYER); // settle as a new town
  242. command_id = 0;
  243. rc = 1;
  244. info.disp();
  245. break;
  246. case COMMAND_SET_CARAVAN_STOP:
  247. if(unit_array[command_unit_recno]->is_visible())
  248. {
  249. UnitCaravan* unitPtr = (UnitCaravan*) unit_array[command_unit_recno];
  250. err_when( unitPtr->unit_id != UNIT_CARAVAN );
  251. // find the firm it is pointing
  252. Location *locPtr = world.get_loc(curXLoc, curYLoc);
  253. Firm *firmPtr;
  254. if( locPtr->is_firm() && (firmPtr = firm_array[locPtr->firm_recno()])
  255. && unitPtr->can_set_stop(firmPtr->firm_recno) )
  256. {
  257. if( se_res.mark_command_time() )
  258. {
  259. se_res.far_sound( unitPtr->cur_x_loc(), unitPtr->cur_y_loc(), 1,
  260. 'S', unitPtr->sprite_id, "ACK");
  261. }
  262. unitPtr->set_stop(command_para, curXLoc, curYLoc, COMMAND_PLAYER); // command_para is the id. of the stop
  263. }
  264. }
  265. command_id = 0;
  266. rc = 1;
  267. break;
  268. case COMMAND_SET_SHIP_STOP:
  269. if(unit_array[command_unit_recno]->is_visible())
  270. {
  271. UnitMarine* unitPtr = (UnitMarine*) unit_array[command_unit_recno];
  272. err_when( unit_res[unitPtr->unit_id]->mobile_type != UNIT_SEA );
  273. // find the firm it is pointing
  274. Location *locPtr = world.get_loc(curXLoc, curYLoc);
  275. Firm *firmPtr;
  276. if( locPtr->is_firm() && (firmPtr = firm_array[locPtr->firm_recno()])
  277. && unitPtr->can_set_stop(firmPtr->firm_recno) )
  278. {
  279. if( se_res.mark_command_time() )
  280. {
  281. se_res.far_sound( unitPtr->cur_x_loc(), unitPtr->cur_y_loc(), 1,
  282. 'S', unitPtr->sprite_id, "ACK");
  283. }
  284. unitPtr->set_stop(command_para, curXLoc, curYLoc, COMMAND_PLAYER); // command_para is the id. of the stop
  285. }
  286. }
  287. command_id = 0;
  288. rc = 1;
  289. break;
  290. case COMMAND_BUILD_WALL:
  291. world.build_wall_tile(curXLoc, curYLoc, nation_array.player_recno, COMMAND_PLAYER);
  292. rc = 1;
  293. break;
  294. case COMMAND_DESTRUCT_WALL:
  295. world.destruct_wall_tile(curXLoc, curYLoc, nation_array.player_recno, COMMAND_PLAYER);
  296. rc = 1;
  297. break;
  298. case COMMAND_GOD_CAST_POWER:
  299. if(!unit_array.is_deleted(command_unit_recno) && unit_array[command_unit_recno]->is_visible())
  300. {
  301. Unit *cmdUnit = unit_array[command_unit_recno];
  302. if( se_res.mark_command_time() )
  303. {
  304. Unit *repUnit = unit_array[unit_array.selected_recno];
  305. se_res.far_sound( repUnit->cur_x_loc(), repUnit->cur_y_loc(), 1,
  306. 'S', repUnit->sprite_id, "ACK");
  307. }
  308. // ###### begin Gilbert 14/10 ########//
  309. cmdUnit->go_cast_power(curXLoc, curYLoc, command_para, COMMAND_PLAYER);
  310. // ###### end Gilbert 14/10 ########//
  311. }
  312. command_id = 0;
  313. rc = 1;
  314. break;
  315. default:
  316. if( !mouse_cursor.frame_flag )
  317. {
  318. mouse_cursor.set_frame(1, 0);
  319. mouse_cursor.process(mouseX, mouseY);
  320. }
  321. else
  322. mouse_cursor.set_frame(1, 0);
  323. }
  324. }
  325. }
  326. if( mouseX >= MAP_X1 && mouseX <= MAP_X2 && // if the mouse is inside the zoom area
  327. mouseY >= MAP_Y1 && mouseY <= MAP_Y2 )
  328. {
  329. mouse.set_boundary(MAP_X1, MAP_Y1, MAP_X2, MAP_Y2);
  330. }
  331. }
  332. //------- the selection action is complete --------//
  333. else if( mouse.mouse_event_type == LEFT_BUTTON_RELEASE)
  334. {
  335. int mouseX = mouse.click_x(LEFT_BUTTON);
  336. int mouseY = mouse.click_y(LEFT_BUTTON);
  337. int mouseReleaseX = mouse.release_x(LEFT_BUTTON);
  338. int mouseReleaseY = mouse.release_y(LEFT_BUTTON);
  339. //-------- reset boundary of mouse -------//
  340. mouse.reset_boundary();
  341. if( mouse_cursor.frame_flag )
  342. {
  343. mouse_cursor.process(mouseReleaseX, mouseReleaseY);
  344. mouse_cursor.set_frame(0);
  345. rc = detect_select( mouse_cursor.frame_x1, mouse_cursor.frame_y1,
  346. mouse_cursor.frame_x2, mouse_cursor.frame_y2,
  347. 0, mouse.event_skey_state & SHIFT_KEY_MASK);
  348. }
  349. }
  350. }
  351. else
  352. {
  353. // no mouse event but keep pressing left button
  354. if( mouse.left_press )
  355. {
  356. if( mouse_cursor.frame_flag )
  357. {
  358. mouse_cursor.process(mouse.cur_x, mouse.cur_y);
  359. }
  360. }
  361. else
  362. {
  363. mouse_cursor.set_frame(0);
  364. }
  365. }
  366. return rc;
  367. }
  368. //--------- End of function Power::detect_frame ---------//
  369. //-------- Begin of function Power::detect_action --------//
  370. //
  371. // return: <int> 1 - action executed.
  372. // 0 - no action ordered.
  373. //
  374. int Power::detect_action()
  375. {
  376. if( !mouse.has_mouse_event || mouse.mouse_event_type != RIGHT_BUTTON || !nation_array.player_recno)
  377. return 0;
  378. int curXLoc, curYLoc;
  379. // int shiftPressed = GetKeyState(VK_SHIFT) & 0X0100; // return the current real-time key state
  380. int shiftPressed = mouse.event_skey_state & SHIFT_KEY_MASK;
  381. int mouseX = mouse.click_x(RIGHT_BUTTON);
  382. int mouseY = mouse.click_y(RIGHT_BUTTON);
  383. //--------- if click on the zoom window --------//
  384. if( mouseX >= ZOOM_X1 && mouseX <= ZOOM_X2 && // if the mouse is inside the zoom area
  385. mouseY >= ZOOM_Y1 && mouseY <= ZOOM_Y2 )
  386. {
  387. curXLoc = world.zoom_matrix->top_x_loc + (mouseX-ZOOM_X1)/ZOOM_LOC_WIDTH;
  388. curYLoc = world.zoom_matrix->top_y_loc + (mouseY-ZOOM_Y1)/ZOOM_LOC_HEIGHT;
  389. }
  390. //---------- if click on the map window -----------//
  391. else if( mouseX >= MAP_X1 && mouseX <= MAP_X2 && // if the mouse is inside the zoom area
  392. mouseY >= MAP_Y1 && mouseY <= MAP_Y2 )
  393. {
  394. curXLoc = world.map_matrix->top_x_loc + (mouseX-MAP_X1);
  395. curYLoc = world.map_matrix->top_y_loc + (mouseY-MAP_Y1);
  396. }
  397. else
  398. {
  399. return 0;
  400. }
  401. //-------- find out how many units have been selected --------//
  402. int selectedCount=0;
  403. short* selectedArray;
  404. Unit* unitPtr;
  405. selectedArray = (short*) mem_add( sizeof(short) * unit_array.size() );
  406. int i;
  407. for( i=unit_array.size() ; i>0 ; i-- )
  408. {
  409. if( unit_array.is_deleted(i) )
  410. continue;
  411. unitPtr = unit_array[i];
  412. if(unitPtr->hit_points<=0 || unitPtr->cur_action==SPRITE_DIE || unitPtr->action_mode==ACTION_DIE)
  413. continue;
  414. if( !unitPtr->selected_flag || !unitPtr->is_visible() )
  415. continue;
  416. if( !unitPtr->is_own() ) // only if the unit belongs to us (a spy is also okay if true_nation_recno is ours)
  417. continue;
  418. selectedArray[selectedCount++] = i;
  419. }
  420. //### begin alex 16/10 ###//
  421. if((mouse.event_skey_state & ALT_KEY_MASK))
  422. {
  423. unit_array.add_way_point(curXLoc, curYLoc, selectedArray, selectedCount, COMMAND_PLAYER);
  424. mem_del(selectedArray);
  425. return 1;
  426. }
  427. //#### end alex 16/10 ####//
  428. if( selectedCount==0 ) // no unit selected
  429. {
  430. mem_del(selectedArray);
  431. return 0;
  432. }
  433. //----- get the info of the clicked location ------//
  434. Location* locPtr=test_detect(mouse.cur_x, mouse.cur_y);
  435. Unit *targetUnit=NULL, *targetShip=NULL, *targetAirUnit=NULL;
  436. Firm* targetFirm=NULL;
  437. Town* targetTown=NULL;
  438. char targetWall=0;
  439. Unit* activeUnit = unit_array[selectedArray[0]];
  440. int mobileType = activeUnit->mobile_type; // mobile type of the selected units
  441. int targetMobileType=0;
  442. short nationRecno = activeUnit->nation_recno;
  443. int retFlag = 0;
  444. if( locPtr )
  445. {
  446. //targetMobileType = locPtr->has_any_unit(mobileType);
  447. targetMobileType = locPtr->has_any_unit();
  448. if(targetMobileType)
  449. {
  450. switch(targetMobileType)
  451. {
  452. case UNIT_LAND:
  453. targetUnit = unit_array[locPtr->unit_recno(targetMobileType)];
  454. err_when(!targetUnit->is_visible());
  455. break;
  456. case UNIT_SEA:
  457. targetShip = unit_array[locPtr->unit_recno(targetMobileType)];
  458. err_when(!targetShip->is_visible());
  459. break;
  460. case UNIT_AIR:
  461. targetAirUnit = unit_array[locPtr->unit_recno(targetMobileType)];
  462. err_when(!targetAirUnit->is_visible());
  463. break;
  464. default: err_here();
  465. break;
  466. }
  467. }
  468. else if( locPtr->is_firm() )
  469. targetFirm = firm_array[locPtr->firm_recno()];
  470. else if( locPtr->is_town() )
  471. targetTown = town_array[locPtr->town_recno()];
  472. else if( locPtr->is_wall() )
  473. targetWall = 1;
  474. }
  475. //--------------- divide by nation ---------------//
  476. static short nationUnitCount[MAX_NATION+1]; // plus one for independent nation
  477. short *nationUnitCountPtr = nationUnitCount;
  478. divide_by_nation(nationUnitCountPtr, selectedArray, selectedCount);
  479. //------------- process action for each nation -------------//
  480. nationUnitCountPtr = nationUnitCount;
  481. Nation *nationPtr;
  482. short *nationSelectedArray;
  483. short nationSelectedCount;
  484. int isHuman;
  485. for(int natCount=0, preNatCount=0; natCount<=MAX_NATION; natCount++, nationUnitCountPtr++)
  486. {
  487. if(!(*nationUnitCountPtr) || (*nationUnitCountPtr)==preNatCount)
  488. continue; // no unit in this nation
  489. nationSelectedArray = selectedArray + preNatCount;
  490. nationSelectedCount = *nationUnitCountPtr - preNatCount;
  491. preNatCount = *nationUnitCountPtr;
  492. nationPtr = (nation_divide_order[natCount]) ? nation_array[nation_divide_order[natCount]] : NULL;
  493. //---------- if the target is a unit -----------//
  494. //### begin alex 19/3 ###//
  495. //activeUnit = unit_array[nationSelectedArray[0]]; // update activeUnit for each nation
  496. activeUnit = unit_array[select_active_unit(nationSelectedArray, nationSelectedCount)]; // update activeUnit for each nation
  497. //#### end alex 19/3 ####//
  498. isHuman = unit_res[activeUnit->unit_id]->race_id > 0; // whether the unit can be assigned to firms and towns
  499. if(targetMobileType)
  500. {
  501. if(targetUnit && targetUnit->hit_points>0)
  502. {
  503. //--- embarking horse/elephants, when targetUnit->nation_recno==0, the unit is an animal ---//
  504. if( unit_res[activeUnit->unit_id]->vehicle_id == targetUnit->unit_id )
  505. {
  506. unit_array.assign(targetUnit->next_x_loc(), targetUnit->next_y_loc(), 0, COMMAND_PLAYER, nationSelectedArray, nationSelectedCount );
  507. retFlag = 1;
  508. }
  509. else if( !targetUnit->is_own() )
  510. {
  511. if( nationPtr && nationPtr->get_relation_should_attack(targetUnit->nation_recno)
  512. && activeUnit->attack_count > 0 ) // Units like Phoenix that can't attack will call move_to() instead of calling attack()
  513. {
  514. if(nation_array.player_recno==nation_divide_order[natCount])
  515. unit_array.attack(targetUnit->next_x_loc(), targetUnit->next_y_loc(), 0, nationSelectedArray, nationSelectedCount, COMMAND_PLAYER, targetUnit->sprite_recno);
  516. }
  517. else
  518. {
  519. unit_array.move_to(curXLoc, curYLoc, 0, nationSelectedArray, nationSelectedCount, COMMAND_PLAYER);
  520. }
  521. retFlag = 1;
  522. }
  523. else if( targetUnit->is_own() && targetUnit->unit_id == UNIT_EXPLOSIVE_CART && shiftPressed)
  524. {
  525. if(nation_array.player_recno==nation_divide_order[natCount])
  526. unit_array.attack(targetUnit->next_x_loc(), targetUnit->next_y_loc(), 0, nationSelectedArray, nationSelectedCount, COMMAND_PLAYER, targetUnit->sprite_recno);
  527. retFlag = 1;
  528. }
  529. // else, right click on other land unit, it is team select
  530. }
  531. else if(targetShip && targetShip->hit_points>0)
  532. {
  533. if(targetShip->is_own() )
  534. {
  535. if(unit_res[targetShip->unit_id]->carry_unit_capacity>0)
  536. {
  537. // ##### patch begin Gilbert 5/8 #######//
  538. unit_array.assign_to_ship(targetShip->next_x_loc(), targetShip->next_y_loc(), 0, nationSelectedArray, nationSelectedCount, COMMAND_PLAYER, targetShip->sprite_recno );
  539. // ##### patch end Gilbert 5/8 #######//
  540. }
  541. }
  542. else
  543. {
  544. if( nationPtr && nationPtr->get_relation_should_attack(targetShip->nation_recno)
  545. && activeUnit->attack_count > 0 ) // Units like Phoenix that can't attack will call move_to() instead of calling attack()
  546. {
  547. if(nation_array.player_recno==nation_divide_order[natCount])
  548. unit_array.attack(targetShip->next_x_loc(), targetShip->next_y_loc(), 0, nationSelectedArray, nationSelectedCount, COMMAND_PLAYER, targetShip->sprite_recno);
  549. }
  550. else
  551. {
  552. unit_array.move_to(curXLoc, curYLoc, 0, nationSelectedArray, nationSelectedCount, COMMAND_PLAYER);
  553. }
  554. }
  555. retFlag = 1;
  556. }
  557. else if(targetAirUnit && targetAirUnit->hit_points>0)
  558. {
  559. if( nationPtr && nationPtr->get_relation_should_attack(targetAirUnit->nation_recno)
  560. && activeUnit->attack_count > 0 ) // Units like Phoenix that can't attack will call move_to() instead of calling attack()
  561. {
  562. if(nation_array.player_recno==nation_divide_order[natCount])
  563. unit_array.attack(targetAirUnit->next_x_loc(), targetAirUnit->next_y_loc(), 0, nationSelectedArray, nationSelectedCount, COMMAND_PLAYER, targetAirUnit->sprite_recno);
  564. }
  565. else
  566. {
  567. unit_array.move_to(curXLoc, curYLoc, 0, nationSelectedArray, nationSelectedCount, COMMAND_PLAYER);
  568. }
  569. retFlag = 1;
  570. }
  571. }
  572. else if(targetFirm && targetFirm->hit_points>0)
  573. {
  574. //-------- if this firm does not belong to the player -------//
  575. int assignedFlag=0;
  576. if( ( ( nationPtr && nationPtr->get_relation_should_attack(targetFirm->nation_recno) )
  577. || shiftPressed ) && activeUnit->attack_count > 0 ) // Units like Phoenix that can't attack will call move_to() instead of calling attack()
  578. {
  579. //------------ attack the firm -------------//
  580. if(nation_array.player_recno==nation_divide_order[natCount])
  581. unit_array.attack(targetFirm->loc_x1, targetFirm->loc_y1, 0, nationSelectedArray, nationSelectedCount, COMMAND_PLAYER, 0);
  582. }
  583. else
  584. {
  585. //------------ filtering for firm_can_assign() ---------------//
  586. int canAssign;
  587. if(targetFirm->firm_id==FIRM_BASE)
  588. {
  589. canAssign = 0;
  590. Unit *selectedUnit;
  591. for(int i=0; i<nationSelectedCount; i++)
  592. {
  593. selectedUnit = unit_array[nationSelectedArray[i]];
  594. // ####### begin Gilbert 22/10 #########//
  595. // if(selectedUnit->firm_can_assign(targetFirm->firm_recno))
  596. if( unit_can_assign_firm(nationSelectedArray[i], targetFirm->firm_recno, nation_array.player_recno) )
  597. // ####### end Gilbert 22/10 #########//
  598. {
  599. canAssign = 1;
  600. break;
  601. }
  602. }
  603. }
  604. else
  605. // ####### begin Gilbert 22/10 #########//
  606. // canAssign = activeUnit->firm_can_assign(targetFirm->firm_recno);
  607. canAssign = unit_can_assign_firm(activeUnit->sprite_recno, targetFirm->firm_recno, nation_array.player_recno);
  608. // ####### begin Gilbert 22/10 #########//
  609. if( canAssign && (isHuman || targetFirm->firm_id==FIRM_CAMP) )
  610. {
  611. //### begin alex 19/3 ###//
  612. err_when(targetFirm->nation_recno != activeUnit->nation_recno);
  613. //#### end alex 19/3 ####//
  614. //----- if own firm, assign the unit to the firm ----//
  615. if(targetFirm->firm_id==FIRM_CAMP)
  616. unit_array.assign_to_camp(targetFirm->loc_x1, targetFirm->loc_y1, COMMAND_PLAYER, nationSelectedArray, nationSelectedCount);
  617. else
  618. unit_array.assign(targetFirm->loc_x1, targetFirm->loc_y1, 0, COMMAND_PLAYER, nationSelectedArray, nationSelectedCount);
  619. }
  620. //### begin alex 19/3 ###//
  621. //else if( activeUnit->mobile_type == UNIT_SEA && targetFirm->firm_id == FIRM_HARBOR )
  622. else if( canAssign && activeUnit->mobile_type == UNIT_SEA && targetFirm->firm_id == FIRM_HARBOR )
  623. {
  624. err_when(targetFirm->nation_recno != activeUnit->nation_recno);
  625. //#### end alex 19/3 ####//
  626. //----- if the selected are marine units -----//
  627. unit_array.assign(targetFirm->loc_x1, targetFirm->loc_y1, 0, COMMAND_PLAYER, nationSelectedArray, nationSelectedCount);
  628. }
  629. else
  630. {
  631. //------- if no other action executed, move to the clicked location ------//
  632. unit_array.move_to(curXLoc, curYLoc, 0, nationSelectedArray, nationSelectedCount, COMMAND_PLAYER);
  633. }
  634. }
  635. retFlag = 1;
  636. }
  637. else if(targetTown)
  638. {
  639. if( activeUnit->spy_recno && activeUnit->nation_recno == targetTown->nation_recno )
  640. {
  641. //------ if the player is sending a spy into the town ------//
  642. unit_array.assign(targetTown->loc_x1, targetTown->loc_y1, 0, COMMAND_PLAYER, nationSelectedArray, nationSelectedCount);
  643. }
  644. else if( isHuman && targetTown->nation_recno == nation_array.player_recno ) // assign to the firm
  645. {
  646. //----- assign units into a town in a normal operation -----//
  647. //--- divide the array, non-skill peasant units are assigned to towns, skilled, soldiers and generals are not assigned to town, they just move close to the town ---//
  648. short* moveArray = (short*) mem_add( sizeof(short) * nationSelectedCount );
  649. short* assignArray = (short*) mem_add( sizeof(short) * nationSelectedCount );
  650. int moveCount=0, assignCount=0;
  651. for( i=0 ; i<nationSelectedCount ; i++ )
  652. {
  653. unitPtr = unit_array[nationSelectedArray[i]];
  654. if(unitPtr->mobile_type==UNIT_LAND && unitPtr->rank_id==RANK_SOLDIER && unitPtr->skill.skill_id<=0)
  655. assignArray[assignCount++] = nationSelectedArray[i];
  656. else
  657. moveArray[moveCount++] = nationSelectedArray[i];
  658. }
  659. if( moveCount > 0 )
  660. unit_array.move_to(targetTown->loc_x1, targetTown->loc_y1, 0, moveArray, moveCount, COMMAND_PLAYER);
  661. if( assignCount > 0 )
  662. {
  663. //### begin alex 19/3 ###//
  664. err_when(targetTown->nation_recno != activeUnit->nation_recno);
  665. //#### end alex 19/3 ####//
  666. unit_array.assign(targetTown->loc_x1, targetTown->loc_y1, 0, COMMAND_PLAYER, assignArray, assignCount);
  667. }
  668. mem_del(moveArray);
  669. mem_del(assignArray);
  670. }
  671. else if( nationPtr && nationPtr->get_relation_should_attack(targetTown->nation_recno)
  672. && activeUnit->attack_count > 0 ) // Units like Phoenix that can't attack will call move_to() instead of calling attack()
  673. {
  674. //--------- attack the town ------------//
  675. if(nation_array.player_recno==nation_divide_order[natCount])
  676. unit_array.attack(targetTown->loc_x1, targetTown->loc_y1, 0, nationSelectedArray, nationSelectedCount, COMMAND_PLAYER, 0);
  677. }
  678. else
  679. unit_array.move_to(curXLoc, curYLoc, 0, nationSelectedArray, nationSelectedCount, COMMAND_PLAYER);
  680. retFlag = 1;
  681. }
  682. else
  683. {
  684. //--------- if no target selected, just move to the clicked location --------//
  685. //---- if double-click, force move ------//
  686. if( mouse.click_count(RIGHT_BUTTON) > 1 )
  687. {
  688. if( !remote.is_enable() )
  689. {
  690. for( int j=0 ; j<nationSelectedCount ; j++ )
  691. unit_array[ nationSelectedArray[j] ]->force_move_flag = 1;
  692. }
  693. else
  694. {
  695. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNIT_SET_FORCE_MOVE, sizeof(short)*(1+nationSelectedCount) );
  696. // packet structure : <unit count> <unit recno>...
  697. *shortPtr = nationSelectedCount;
  698. ++shortPtr;
  699. for( int j=0 ; j<nationSelectedCount ; j++, shortPtr++ )
  700. *shortPtr = nationSelectedArray[j];
  701. }
  702. }
  703. //--------- move to now -----------//
  704. unit_array.move_to(curXLoc, curYLoc, 0, nationSelectedArray, nationSelectedCount, COMMAND_PLAYER);
  705. retFlag = 1;
  706. }
  707. //-------- quit checking -------//
  708. if(preNatCount==selectedCount)
  709. break; // all selected Unit is processed
  710. err_when(preNatCount > selectedCount);
  711. }
  712. mem_del(selectedArray);
  713. return retFlag;
  714. }
  715. //--------- End of function Power::detect_action ---------//
  716. //------ Begin of function Power::test_detect -------//
  717. //
  718. // Test detect if there is an object at where the mouse cursor
  719. // is currently pointing at.
  720. //
  721. // return: <Location*> The pointer to the location with a sprite or firm
  722. // being detected.
  723. // NULL - no sprite detected.
  724. // mobileType UNIT_AIR or UNIT_LAND (don't return UNIT_SEA)
  725. //
  726. Location* Power::test_detect(int curX, int curY, char *mobileType)
  727. {
  728. char dummy, tempMobileType;
  729. if( !mobileType )
  730. mobileType = &dummy;
  731. //---- only proceed if the mouse cursor is inside the zoom map area ---//
  732. if( curX < ZOOM_X1 || curX > ZOOM_X2 || // if the mouse is inside the zoom area
  733. curY < ZOOM_Y1 || curY > ZOOM_Y2 )
  734. {
  735. return NULL;
  736. }
  737. //------ if mouse cursor is pointing at a firm, return now ------//
  738. int curXLoc = world.zoom_matrix->top_x_loc + (curX-ZOOM_X1)/ZOOM_LOC_WIDTH;
  739. int curYLoc = world.zoom_matrix->top_y_loc + (curY-ZOOM_Y1)/ZOOM_LOC_HEIGHT;
  740. Location* locPtr = world.get_loc(curXLoc,curYLoc);
  741. //---- expand the area outwards to cover sprites that are in their way moving into the area
  742. int detectSpread = mouse.skey_state & CONTROL_KEY_MASK ? 0 : DETECT_SPREAD;
  743. int selXLoc1=max(0, curXLoc-detectSpread); // expand 2 tiles in case of big sprite
  744. int selYLoc1=max(0, curYLoc-detectSpread);
  745. int selXLoc2=min(MAX_WORLD_X_LOC-1, curXLoc+detectSpread);
  746. int selYLoc2=min(MAX_WORLD_Y_LOC-1, curYLoc+detectSpread);
  747. //---------- select sprite --------------//
  748. int xLoc, yLoc;
  749. Unit *unitPtr;
  750. int absCurX = curX-ZOOM_X1+World::view_top_x; // the mouse cursor's absolute position on the whole world map
  751. int absCurY = curY-ZOOM_Y1+World::view_top_y;
  752. Location* retLoc = NULL;
  753. // first pass : scan air unit
  754. for( yLoc=selYLoc1 ; yLoc<=selYLoc2 ; yLoc++ )
  755. {
  756. locPtr = world.get_loc(selXLoc1, yLoc);
  757. for( xLoc=selXLoc1 ; xLoc<=selXLoc2 ; xLoc++, locPtr++ )
  758. {
  759. if( locPtr->has_unit(UNIT_AIR) && !unit_array.is_deleted(locPtr->air_cargo_recno) ) // if the mouse does not click directly on a sprite
  760. {
  761. unitPtr = unit_array[locPtr->air_cargo_recno];
  762. tempMobileType = UNIT_AIR;
  763. err_when(!unitPtr->is_visible());
  764. err_when( unitPtr->mobile_type != UNIT_AIR );
  765. }
  766. else
  767. unitPtr = NULL;
  768. //----- there is a sprite in the location -----//
  769. if( unitPtr && !unitPtr->is_shealth() )
  770. {
  771. unitPtr->update_abs_pos();
  772. if( absCurX >= unitPtr->abs_x1 && absCurY >= unitPtr->abs_y1 &&
  773. absCurX <= unitPtr->abs_x2 && absCurY <= unitPtr->abs_y2 )
  774. {
  775. retLoc = locPtr;
  776. *mobileType = tempMobileType;
  777. }
  778. }
  779. }
  780. }
  781. if( retLoc )
  782. return retLoc;
  783. // -------- second pass : scan land firm/town/wall --------//
  784. locPtr = world.get_loc(curXLoc, curYLoc);
  785. if( locPtr->is_firm() || locPtr->is_town() || locPtr->is_wall() )
  786. {
  787. *mobileType = UNIT_LAND;
  788. return locPtr;
  789. }
  790. //---------- third pass : scan land unit -------------//
  791. for( yLoc=selYLoc1 ; yLoc<=selYLoc2 ; yLoc++ )
  792. {
  793. locPtr = world.get_loc(selXLoc1,yLoc);
  794. for( xLoc=selXLoc1 ; xLoc<=selXLoc2 ; xLoc++, locPtr++ )
  795. {
  796. if( (locPtr->has_unit(UNIT_LAND) || locPtr->has_unit(UNIT_SEA))
  797. && !unit_array.is_deleted(locPtr->cargo_recno) ) // if the mouse does not click directly on a sprite
  798. {
  799. unitPtr = unit_array[locPtr->cargo_recno];
  800. tempMobileType = UNIT_LAND;
  801. err_when(!unitPtr->is_visible());
  802. }
  803. else
  804. unitPtr = NULL;
  805. //----- there is a sprite in the location -----//
  806. if( unitPtr && !unitPtr->is_shealth() )
  807. {
  808. unitPtr->update_abs_pos();
  809. if( absCurX >= unitPtr->abs_x1 && absCurY >= unitPtr->abs_y1 &&
  810. absCurX <= unitPtr->abs_x2 && absCurY <= unitPtr->abs_y2 )
  811. {
  812. retLoc = locPtr;
  813. *mobileType = tempMobileType;
  814. }
  815. }
  816. }
  817. }
  818. return retLoc;
  819. }
  820. //------ End of function Power::test_detect -------//
  821. //------ Begin of function Power::detect_select -------//
  822. //
  823. // This function is called when the mouse has been clicked,
  824. // this function will select the objects inside the mouse selection area,
  825. // and deselect previously selected objects.
  826. //
  827. // <int> selX1, selY1, selX2, selY2 - the positions of the selection box
  828. //
  829. // <int> recallGroup - recall selection of the defined group to which the
  830. // selected unit belongs
  831. //
  832. // <int> shiftSelect - add/remove individual selected unit
  833. //
  834. // return : <int> >0 - no. of units or firms selected
  835. // 0 - no unit or firm detected in the rectd area.
  836. //
  837. int Power::detect_select(int selX1, int selY1, int selX2, int selY2, int recallGroup, int shiftSelect)
  838. {
  839. int topXLoc = world.zoom_matrix->top_x_loc;
  840. int topYLoc = world.zoom_matrix->top_y_loc;
  841. int selXLoc1 = topXLoc + (selX1-ZOOM_X1)/ZOOM_LOC_WIDTH;
  842. int selYLoc1 = topYLoc + (selY1-ZOOM_Y1)/ZOOM_LOC_HEIGHT;
  843. int selXLoc2 = topXLoc + (selX2-ZOOM_X1)/ZOOM_LOC_WIDTH;
  844. int selYLoc2 = topYLoc + (selY2-ZOOM_Y1)/ZOOM_LOC_HEIGHT;
  845. int firstXLoc = selXLoc1, firstYLoc = selYLoc1; // first location to be tested
  846. //-- expand the area outwards to cover sprites that are in their way moving into the area
  847. selXLoc1=max(0, selXLoc1-DETECT_SPREAD); // expand 2 tiles in case of big sprite
  848. selYLoc1=max(0, selYLoc1-DETECT_SPREAD);
  849. selXLoc2=min(MAX_WORLD_X_LOC-1,selXLoc2+DETECT_SPREAD);
  850. selYLoc2=min(MAX_WORLD_Y_LOC-1,selYLoc2+DETECT_SPREAD);
  851. //------ calc absolute positions for fast comparsion ---//
  852. int absSelX1 = selX1-ZOOM_X1+World::view_top_x; // the mouse cursor's absolute position on the whole world map
  853. int absSelY1 = selY1-ZOOM_Y1+World::view_top_y;
  854. int absSelX2 = selX2-ZOOM_X1+World::view_top_x;
  855. int absSelY2 = selY2-ZOOM_Y1+World::view_top_y;
  856. // int shiftSelect = GetKeyState(VK_SHIFT) & 0X0100; // return the current real-time key state
  857. int selectOneOnly = abs(selX1-selX2)<=3 && abs(selY1-selY2)<=3;
  858. //---------- select sprite --------------//
  859. int selectedCount=0; // whether any sprite has been selected.
  860. int xLoc, yLoc;
  861. Location *locPtr;
  862. Unit *unitPtr;
  863. int i;
  864. int selectedSiteRecno=0; //, selectedUnitRecno=0;
  865. int selectedWallXLoc= -1, selectedWallYLoc= -1;
  866. int selectedFirmRecno=0;
  867. int selectedTownRecno=0;
  868. int firstTest=0;
  869. char selectSound = 0;
  870. if( selectOneOnly )
  871. {
  872. char pMobileType;
  873. locPtr = test_detect( selX2, selY2, &pMobileType );
  874. if( locPtr )
  875. {
  876. if( pMobileType == UNIT_AIR && locPtr->has_unit(pMobileType) &&
  877. !unit_array.is_deleted(locPtr->air_cargo_recno) &&
  878. !(unitPtr = unit_array[locPtr->air_cargo_recno])->is_shealth() )
  879. {
  880. err_when( unitPtr->mobile_type != UNIT_AIR );
  881. }
  882. else if( pMobileType == UNIT_LAND &&
  883. (locPtr->has_unit(UNIT_LAND) || locPtr->has_unit(UNIT_SEA)) &&
  884. !unit_array.is_deleted(locPtr->cargo_recno) &&
  885. !(unitPtr = unit_array[locPtr->cargo_recno])->is_shealth() )
  886. {
  887. err_when( unitPtr->mobile_type != UNIT_LAND && unitPtr->mobile_type != UNIT_SEA);
  888. }
  889. else if( pMobileType == UNIT_LAND && !recallGroup &&
  890. locPtr->is_firm() && !firm_array.is_deleted(locPtr->cargo_recno) )
  891. {
  892. selectedFirmRecno=locPtr->firm_recno();
  893. selectedCount++;
  894. unitPtr = NULL;
  895. }
  896. else if( pMobileType == UNIT_LAND && !recallGroup &&
  897. locPtr->is_town() && !town_array.is_deleted(locPtr->cargo_recno) )
  898. {
  899. selectedTownRecno=locPtr->town_recno();
  900. selectedCount++;
  901. unitPtr = NULL;
  902. }
  903. else
  904. unitPtr = NULL;
  905. if( unitPtr &&
  906. (!recallGroup || unitPtr->is_own()) ) // skip recallGroup selecting enemy unit, it is attack!
  907. {
  908. if( !unitPtr->is_own() )
  909. {
  910. err_when( recallGroup ); // press right button on enemy unit is attack, not select
  911. shiftSelect = 0;
  912. }
  913. if( recallGroup && unitPtr->team_id )
  914. {
  915. DWORD teamId = unitPtr->team_id;
  916. char newSelectedFlag = shiftSelect ? (unitPtr->selected_flag ? 0 : 1) : 2;
  917. for( i=unit_array.size() ; i>0 ; i-- )
  918. {
  919. if( unit_array.is_deleted(i) )
  920. continue;
  921. Unit *memberUnit = unit_array[i];
  922. //---- set Unit::team_id to define the group ----//
  923. if( memberUnit->team_id == teamId )
  924. {
  925. memberUnit->selected_flag = newSelectedFlag; // a team member is selected is depending on the clicked unit
  926. selectedCount++;
  927. }
  928. }
  929. }
  930. else
  931. {
  932. char newSelectedFlag = shiftSelect ? (unitPtr->selected_flag ? 0 : 1) : 2;
  933. unitPtr->selected_flag = newSelectedFlag;
  934. selectedCount++;
  935. }
  936. if( unitPtr->selected_flag && unitPtr->is_own() && nation_array.player_recno)
  937. {
  938. if( se_res.mark_select_object_time() )
  939. {
  940. se_res.sound( unitPtr->cur_x_loc(), unitPtr->cur_y_loc(), 1,
  941. 'S', unitPtr->sprite_id, "SEL");
  942. }
  943. selectSound = 1;
  944. }
  945. // goto label_post_select;
  946. }
  947. }
  948. }
  949. else
  950. {
  951. const unsigned int mobileTypeCount = 3;
  952. static char mobileTypeList[mobileTypeCount] = { UNIT_AIR, UNIT_LAND, UNIT_SEA };
  953. // pass 1 - find if selecting own nation or spy cloaked nation
  954. short nationSelect = nation_array.player_recno;
  955. if( shiftSelect && unit_array.selected_recno )
  956. {
  957. if( !unit_array.is_deleted(unit_array.selected_recno) )
  958. nationSelect = unit_array[unit_array.selected_recno]->nation_recno;
  959. // so if you want to select spy of the same nation from
  960. // from a crowd of your spy,
  961. // select any one spy of that nation, shift select the crowd
  962. }
  963. else
  964. {
  965. unsigned short selectNationCount[MAX_NATION+1]; // count nation of selectable unit
  966. memset( selectNationCount, 0, sizeof(selectNationCount) );
  967. for( yLoc=selYLoc1 ; yLoc<=selYLoc2 ; yLoc++ )
  968. {
  969. for( xLoc=selXLoc1 ; xLoc<=selXLoc2 ; xLoc++ )
  970. {
  971. locPtr = world.get_loc(xLoc, yLoc);
  972. for( int mt = 0; mt < sizeof(mobileTypeList)/sizeof(char); ++mt )
  973. {
  974. char mobileType = mobileTypeList[mt];
  975. if( locPtr->has_unit(mobileType) && !unit_array.is_deleted(locPtr->unit_recno(mobileType))
  976. && !(unitPtr = unit_array[locPtr->unit_recno(mobileType)])->is_shealth() )
  977. {
  978. if(!unitPtr->is_visible() || unitPtr->hit_points<=0 || unitPtr->is_shealth() ||
  979. !unitPtr->is_own() )
  980. continue; // skip this unit
  981. unitPtr->update_abs_pos();
  982. if( m.is_touch( absSelX1, absSelY1, absSelX2, absSelY2,
  983. unitPtr->abs_x1, unitPtr->abs_y1,
  984. unitPtr->abs_x2, unitPtr->abs_y2 ) )
  985. {
  986. selectNationCount[unitPtr->nation_recno]++;
  987. }
  988. }
  989. }
  990. }
  991. }
  992. if( selectNationCount[nation_array.player_recno] == 0 ) // prefer own nation
  993. {
  994. nationSelect = -1; // all nation
  995. }
  996. }
  997. // recallGroup is ignored
  998. char newSelectedFlag = shiftSelect ? 1 : 2; // press shift to include more units
  999. for( yLoc=selYLoc1 ; yLoc<=selYLoc2 ; yLoc++ )
  1000. {
  1001. for( xLoc=selXLoc1 ; xLoc<=selXLoc2 ; xLoc++ )
  1002. {
  1003. locPtr = world.get_loc(xLoc, yLoc);
  1004. for( int mt = 0; mt < sizeof(mobileTypeList)/sizeof(char); ++mt )
  1005. {
  1006. char mobileType = mobileTypeList[mt];
  1007. if( locPtr->has_unit(mobileType) && !unit_array.is_deleted(locPtr->unit_recno(mobileType))
  1008. && !(unitPtr = unit_array[locPtr->unit_recno(mobileType)])->is_shealth() )
  1009. {
  1010. if(!unitPtr->is_visible() || unitPtr->hit_points<=0 || unitPtr->is_shealth() ||
  1011. !unitPtr->is_own() )
  1012. continue; // skip this unit
  1013. if( nationSelect != -1 && unitPtr->nation_recno != nationSelect )
  1014. continue; // skip this unit
  1015. unitPtr->update_abs_pos();
  1016. if( m.is_touch( absSelX1, absSelY1, absSelX2, absSelY2,
  1017. unitPtr->abs_x1, unitPtr->abs_y1,
  1018. unitPtr->abs_x2, unitPtr->abs_y2 ) )
  1019. {
  1020. selectedCount++;
  1021. //selectedUnitRecno = unitPtr->sprite_recno;
  1022. //--------- set selected_flag ----------//
  1023. unitPtr->selected_flag = newSelectedFlag; // set to 2 as all sprites will be processed below
  1024. //---- recall selection of the defined group to which the selected unit belongs ----//
  1025. }
  1026. }
  1027. }
  1028. }
  1029. }
  1030. }
  1031. //-------- detect raw material sites ---------//
  1032. if( selectedCount==0 && selectOneOnly && !recallGroup )
  1033. {
  1034. int selXLoc = topXLoc + (selX1-ZOOM_X1)/ZOOM_LOC_WIDTH;
  1035. int selYLoc = topYLoc + (selY1-ZOOM_Y1)/ZOOM_LOC_HEIGHT;
  1036. Location* locPtr = world.get_loc(selXLoc, selYLoc);
  1037. if( locPtr->has_site() && !locPtr->is_firm() )
  1038. {
  1039. selectedCount++;
  1040. selectedSiteRecno = locPtr->site_recno();
  1041. }
  1042. }
  1043. //---------- detect city wall ----------//
  1044. if( selectedCount==0 && selectOneOnly && !recallGroup )
  1045. {
  1046. int selXLoc = topXLoc + (selX1-ZOOM_X1)/ZOOM_LOC_WIDTH;
  1047. int selYLoc = topYLoc + (selY1-ZOOM_Y1)/ZOOM_LOC_HEIGHT;
  1048. Location* locPtr = world.get_loc(selXLoc, selYLoc);
  1049. if( locPtr->is_wall() )
  1050. {
  1051. selectedCount++;
  1052. selectedWallXLoc = selXLoc;
  1053. selectedWallYLoc = selYLoc;
  1054. }
  1055. }
  1056. //------ if any objects have been just selected ------//
  1057. // label_post_select:
  1058. if( selectedCount ) // reset previously selected flag
  1059. {
  1060. //--- if shift select, don't change the selected flag, but if town or firm is selected, reset all unit selection ---//
  1061. if( selectedFirmRecno || selectedTownRecno || selectedSiteRecno || selectedWallXLoc >= 0 || !shiftSelect )
  1062. {
  1063. for( i=unit_array.size() ; i>0 ; i-- )
  1064. {
  1065. if( unit_array.is_deleted(i) )
  1066. continue;
  1067. unitPtr = unit_array[i];
  1068. if( unitPtr->selected_flag )
  1069. {
  1070. //---- for group selection (selecting more than 1 unit), only select the player's own units ----//
  1071. if( selectedCount>1 && !unitPtr->is_own() )
  1072. unitPtr->selected_flag = 0;
  1073. else
  1074. unitPtr->selected_flag--;
  1075. // for newly selected sprite, selected_flag will be changed from 2 to 1
  1076. // for formerly selected sprite, selected_flag will be change from 1 to 0
  1077. }
  1078. }
  1079. }
  1080. //--------- count the no. of selected units --------//
  1081. //
  1082. // we need to count it instead of using selectedCount as
  1083. // selectedCount only tells the no. of units selected
  1084. // this time, not including previous selected ones for shift selection.
  1085. //
  1086. //--------------------------------------------------//
  1087. unit_array.selected_count=0; // reset it now, we will count it below
  1088. int highRankUnitRecno = 0;
  1089. //--- unit_array.selected_recno should be the unit with the highest rank ---//
  1090. for( i=unit_array.size() ; i>0 ; i-- )
  1091. {
  1092. if( !unit_array.is_deleted(i) && unit_array[i]->selected_flag )
  1093. {
  1094. unit_array.selected_count++;
  1095. if( !highRankUnitRecno ||
  1096. unit_array[i]->rank_id > unit_array[highRankUnitRecno]->rank_id )
  1097. highRankUnitRecno = i;
  1098. }
  1099. }
  1100. unit_array.selected_recno=highRankUnitRecno; // note no unit may be selected, like pressing shift to de-select unit
  1101. // so selectedCount may not be true
  1102. if( unit_array.selected_recno && !selectSound &&
  1103. unit_array[unit_array.selected_recno]->is_own() )
  1104. {
  1105. if( se_res.mark_select_object_time() )
  1106. {
  1107. Unit *headUnit = unit_array[unit_array.selected_recno];
  1108. se_res.sound( headUnit->cur_x_loc(), headUnit->cur_y_loc(), 1, 'S',
  1109. headUnit->sprite_id, "SEL");
  1110. }
  1111. selectSound = 1;
  1112. }
  1113. if( selectedFirmRecno && !selectSound &&
  1114. firm_array[selectedFirmRecno]->own_firm() )
  1115. {
  1116. if( se_res.mark_select_object_time() )
  1117. {
  1118. Firm *firmPtr = firm_array[selectedFirmRecno];
  1119. se_res.sound(firmPtr->center_x, firmPtr->center_y, 1,
  1120. 'F', firmPtr->firm_id, firmPtr->under_construction ? (char*)"SELU" : (char*)"SEL" );
  1121. }
  1122. selectSound = 1;
  1123. }
  1124. if( selectedTownRecno && !selectSound &&
  1125. town_array[selectedTownRecno]->nation_recno == nation_array.player_recno )
  1126. {
  1127. if( se_res.mark_select_object_time() )
  1128. {
  1129. Town *townPtr = town_array[selectedTownRecno];
  1130. se_res.sound(townPtr->center_x, townPtr->center_y, 1,
  1131. 'T', 0, "SEL" );
  1132. }
  1133. selectSound = 1;
  1134. }
  1135. //--- only set selected_recno for single unit selected, don't do so for nation selection
  1136. firm_array.selected_recno = selectedFirmRecno;
  1137. town_array.selected_recno = selectedTownRecno;
  1138. site_array.selected_recno = selectedSiteRecno;
  1139. wall_res.selected_x_loc = selectedWallXLoc;
  1140. wall_res.selected_y_loc = selectedWallYLoc;
  1141. reset_command(); // reset current command when a new unit is selected
  1142. //--- group them automatically if a group of units are selected ---//
  1143. // if( unit_array.selected_count > 1 )
  1144. // unit_array[unit_array.selected_recno]->define_team();
  1145. //----- refresh info display of the selected object -----//
  1146. info.disp();
  1147. }
  1148. //-----------------------------------------//
  1149. return selectedCount;
  1150. }
  1151. //------ End of function Power::detect_select -------//
  1152. //--------- Begin of function Power::issue_command ---------//
  1153. //
  1154. // <int> commandId - the id. of the command
  1155. // [int] commandUnitRecno - the id. of the unit that issues the command
  1156. // [int] commandPara - an extra parameter of the command
  1157. //
  1158. void Power::issue_command(int commandId, int commandUnitRecno, int commandPara)
  1159. {
  1160. command_id = commandId;
  1161. command_unit_recno = commandUnitRecno;
  1162. command_para = commandPara;
  1163. }
  1164. //----------- End of function Power::issue_command -----------//
  1165. //--------- Begin of function Power::reset_selection ---------//
  1166. //
  1167. // Reset selection.
  1168. //
  1169. void Power::reset_selection()
  1170. {
  1171. int i;
  1172. //----- reset unit selection -------//
  1173. for(i=1; i <=unit_array.size() ; i++)
  1174. {
  1175. if( unit_array.is_deleted(i) )
  1176. continue;
  1177. unit_array[i]->selected_flag = 0;
  1178. }
  1179. unit_array.selected_recno = 0;
  1180. unit_array.selected_count = 0;
  1181. //---- reset other selection --------//
  1182. firm_array.selected_recno = 0;
  1183. town_array.selected_recno = 0;
  1184. site_array.selected_recno = 0;
  1185. wall_res.selected_x_loc = -1;
  1186. wall_res.selected_y_loc = -1;
  1187. reset_command(); // reset current command when a new unit is selected
  1188. }
  1189. //----------- End of function Power::reset_selection -----------//
  1190. //--------- Begin of function Power::get_link_icon ---------//
  1191. //
  1192. // <char> linkStatus - link status
  1193. // <int> sameNation - whether the two firms are of the same nation
  1194. // (default: 0)
  1195. //
  1196. // return: <char*> the bitmap pointer of the link icon
  1197. //
  1198. char* Power::get_link_icon(char linkStatus, int sameNation)
  1199. {
  1200. char goodLinkName[9] = "LINK_EE1";
  1201. goodLinkName[7] = '1'+ (char) (sys.frame_count/2%3);
  1202. switch( linkStatus )
  1203. {
  1204. case LINK_EE:
  1205. return image_icon.get_ptr(goodLinkName);
  1206. case LINK_ED:
  1207. return image_icon.get_ptr("LINK_ED");
  1208. case LINK_DE:
  1209. return image_icon.get_ptr("LINK_DE");
  1210. case LINK_DD:
  1211. if( sameNation )
  1212. return image_icon.get_ptr("LINK_DE"); // green cross for same nation firms
  1213. else
  1214. return image_icon.get_ptr("LINK_DD"); // red cross for different nation firms
  1215. }
  1216. err_here();
  1217. return NULL;
  1218. }
  1219. //----------- End of function Power::get_link_icon -----------//
  1220. // ---------- Begin of function Power::choose_cursor --------//
  1221. //
  1222. int Power::choose_cursor(int scrnX, int scrnY,
  1223. ScreenObjectType selectedObjectType, short selectedObjectRecno,
  1224. ScreenObjectType pointingObjectType, short pointingObjectRecno)
  1225. {
  1226. int selectedObjectId = 0;
  1227. int pointingObjectId = 0;
  1228. if(command_id)
  1229. {
  1230. if( scrnX >= ZOOM_X1 && scrnX <= ZOOM_X2 &&
  1231. scrnY >= ZOOM_Y1 && scrnY <= ZOOM_Y2)
  1232. {
  1233. switch(command_id)
  1234. {
  1235. case COMMAND_BUILD_FIRM:
  1236. return CURSOR_BUILD;
  1237. case COMMAND_ASSIGN:
  1238. return CURSOR_ASSIGN;
  1239. case COMMAND_BURN:
  1240. return CURSOR_BURN;
  1241. case COMMAND_SETTLE:
  1242. {
  1243. char flagColor = 0; // CURSOR_SETTLE + 0 is a valid cursor
  1244. Unit *activeUnit;
  1245. if( nation_array.player_recno
  1246. && !nation_array.is_deleted(nation_array.player_recno) )
  1247. flagColor = (~nation_array)->color_scheme_id;
  1248. if( command_unit_recno && !unit_array.is_deleted(command_unit_recno)
  1249. && (activeUnit = unit_array[command_unit_recno]) )
  1250. {
  1251. if( !activeUnit->nation_recno )
  1252. flagColor = 0; // independent nation
  1253. else if( !nation_array.is_deleted(activeUnit->nation_recno) )
  1254. flagColor = nation_array[activeUnit->nation_recno]->color_scheme_id;
  1255. }
  1256. return CURSOR_SETTLE + flagColor;
  1257. }
  1258. case COMMAND_SET_CARAVAN_STOP:
  1259. if(
  1260. (
  1261. pointingObjectType == SCREEN_OBJECT_FRIEND_FIRM
  1262. ||
  1263. pointingObjectType == SCREEN_OBJECT_ENEMY_FIRM
  1264. )
  1265. &&
  1266. !nation_array.is_deleted(firm_array[pointingObjectRecno]->nation_recno)
  1267. &&
  1268. ((UnitCaravan *)unit_array[selectedObjectRecno])->can_set_stop(pointingObjectRecno)
  1269. )
  1270. return CURSOR_SET_STOP;
  1271. return CURSOR_CANT_SET_STOP;
  1272. case COMMAND_SET_SHIP_STOP:
  1273. if(
  1274. (
  1275. pointingObjectType == SCREEN_OBJECT_FRIEND_FIRM
  1276. ||
  1277. pointingObjectType == SCREEN_OBJECT_ENEMY_FIRM
  1278. )
  1279. &&
  1280. !nation_array.is_deleted(firm_array[pointingObjectRecno]->nation_recno)
  1281. &&
  1282. ((UnitMarine *)unit_array[selectedObjectRecno])->can_set_stop(pointingObjectRecno)
  1283. )
  1284. return CURSOR_SHIP_STOP;
  1285. return CURSOR_CANT_SHIP_STOP;
  1286. case COMMAND_BUILD_WALL:
  1287. return CURSOR_BUILD;
  1288. case COMMAND_DESTRUCT_WALL:
  1289. return CURSOR_DESTRUCT;
  1290. case COMMAND_GOD_CAST_POWER:
  1291. return CURSOR_NORMAL;
  1292. default:
  1293. err_here();
  1294. return CURSOR_NORMAL;
  1295. }
  1296. }
  1297. else
  1298. {
  1299. return CURSOR_NORMAL;
  1300. }
  1301. }
  1302. else
  1303. {
  1304. // power.command_id == 0
  1305. // ------- check cursor inside zoom window -------//
  1306. if( scrnX >= ZOOM_X1 && scrnX <= ZOOM_X2 &&
  1307. scrnY >= ZOOM_Y1 && scrnY <= ZOOM_Y2)
  1308. {
  1309. // ------ inside zoom window, depend on selected and pointing object
  1310. switch(selectedObjectType)
  1311. {
  1312. case SCREEN_OBJECT_NONE:
  1313. case SCREEN_OBJECT_WALL:
  1314. case SCREEN_OBJECT_SITE:
  1315. case SCREEN_OBJECT_ENEMY_UNIT:
  1316. {
  1317. switch( pointingObjectType)
  1318. {
  1319. case SCREEN_OBJECT_NONE:
  1320. case SCREEN_OBJECT_WALL:
  1321. case SCREEN_OBJECT_SITE:
  1322. return CURSOR_NORMAL;
  1323. case SCREEN_OBJECT_FRIEND_UNIT:
  1324. case SCREEN_OBJECT_UNIT_GROUP:
  1325. case SCREEN_OBJECT_FRIEND_TOWN:
  1326. case SCREEN_OBJECT_FRIEND_FIRM:
  1327. return CURSOR_NORMAL_C;
  1328. case SCREEN_OBJECT_ENEMY_UNIT:
  1329. case SCREEN_OBJECT_ENEMY_TOWN:
  1330. case SCREEN_OBJECT_ENEMY_FIRM:
  1331. return CURSOR_NORMAL_O;
  1332. default:
  1333. err_here();
  1334. return CURSOR_NORMAL;
  1335. }
  1336. }
  1337. case SCREEN_OBJECT_SPY_UNIT:
  1338. {
  1339. Unit *unitPtr = unit_array[selectedObjectRecno];
  1340. short nationRecno = unitPtr->nation_recno;
  1341. selectedObjectId = unitPtr->unit_id;
  1342. switch( pointingObjectType )
  1343. {
  1344. case SCREEN_OBJECT_NONE:
  1345. case SCREEN_OBJECT_WALL:
  1346. case SCREEN_OBJECT_SITE:
  1347. return CURSOR_NORMAL;
  1348. case SCREEN_OBJECT_FRIEND_UNIT:
  1349. case SCREEN_OBJECT_ENEMY_UNIT:
  1350. {
  1351. Unit *pUnit = unit_array[pointingObjectRecno];
  1352. if( nationRecno == pUnit->nation_recno )
  1353. {
  1354. // same nation
  1355. return choose_cursor_units(selectedObjectRecno, pointingObjectRecno);
  1356. }
  1357. else
  1358. {
  1359. return CURSOR_UNIT_O;
  1360. }
  1361. }
  1362. case SCREEN_OBJECT_FRIEND_TOWN:
  1363. case SCREEN_OBJECT_ENEMY_TOWN:
  1364. {
  1365. Town *pTown = town_array[pointingObjectRecno];
  1366. // determine friend / enemy again
  1367. if( nationRecno == pTown->nation_recno )
  1368. {
  1369. if( unit_res[selectedObjectId]->race_id && unitPtr->rank_id == RANK_SOLDIER )
  1370. return CURSOR_ASSIGN;
  1371. else
  1372. return CURSOR_UNIT_C;
  1373. }
  1374. else
  1375. {
  1376. return CURSOR_UNIT_O;
  1377. }
  1378. }
  1379. case SCREEN_OBJECT_FRIEND_FIRM:
  1380. case SCREEN_OBJECT_ENEMY_FIRM:
  1381. {
  1382. Firm *pFirm = firm_array[pointingObjectRecno];
  1383. // ##### begin Gilbert 22/10 #########//
  1384. //if( unitPtr->firm_can_assign(pointingObjectRecno) )
  1385. if( unit_can_assign_firm(selectedObjectRecno, pointingObjectRecno, nation_array.player_recno) )
  1386. // ##### end Gilbert 22/10 #########//
  1387. return CURSOR_ASSIGN;
  1388. else
  1389. {
  1390. if( nationRecno == pFirm->nation_recno )
  1391. return CURSOR_UNIT_C;
  1392. else
  1393. return CURSOR_UNIT_O;
  1394. }
  1395. }
  1396. default:
  1397. err_here();
  1398. return CURSOR_NORMAL;
  1399. }
  1400. }
  1401. case SCREEN_OBJECT_FRIEND_UNIT:
  1402. {
  1403. Unit *unitPtr = unit_array[selectedObjectRecno];
  1404. selectedObjectId = unitPtr->unit_id;
  1405. char rankId = unitPtr->rank_id;
  1406. switch( pointingObjectType)
  1407. {
  1408. case SCREEN_OBJECT_NONE:
  1409. case SCREEN_OBJECT_SITE:
  1410. return CURSOR_UNIT;
  1411. case SCREEN_OBJECT_FRIEND_UNIT:
  1412. return choose_cursor_units(selectedObjectRecno, pointingObjectRecno);
  1413. case SCREEN_OBJECT_UNIT_GROUP:
  1414. err_here(); // impossible to pointing at more than one unit
  1415. return CURSOR_UNIT_C;
  1416. case SCREEN_OBJECT_FRIEND_TOWN:
  1417. // ##### begin Gilbert 18/10 ######//
  1418. if( unitPtr->race_id && rankId == RANK_SOLDIER && !unitPtr->skill.skill_id)
  1419. // ##### end Gilbert 18/10 ######//
  1420. return CURSOR_ASSIGN;
  1421. else
  1422. return CURSOR_UNIT_C;
  1423. case SCREEN_OBJECT_FRIEND_FIRM:
  1424. {
  1425. Firm *firmPtr = firm_array[pointingObjectRecno];
  1426. pointingObjectId = firmPtr->firm_id;
  1427. // ###### begin Gilbert 22/10 #######//
  1428. // if( unitPtr->firm_can_assign(pointingObjectRecno) )
  1429. if( unit_can_assign_firm(selectedObjectRecno, pointingObjectRecno, nation_array.player_recno) )
  1430. // ###### end Gilbert 22/10 #######//
  1431. return CURSOR_ASSIGN;
  1432. return CURSOR_UNIT_C;
  1433. }
  1434. case SCREEN_OBJECT_ENEMY_UNIT:
  1435. case SCREEN_OBJECT_ENEMY_TOWN:
  1436. case SCREEN_OBJECT_ENEMY_FIRM:
  1437. return CURSOR_UNIT_O;
  1438. case SCREEN_OBJECT_WALL:
  1439. return CURSOR_DESTRUCT;
  1440. default:
  1441. err_here();
  1442. return CURSOR_UNIT;
  1443. }
  1444. }
  1445. case SCREEN_OBJECT_UNIT_GROUP:
  1446. {
  1447. int arraySize = unit_array.size();
  1448. int i;
  1449. switch( pointingObjectType)
  1450. {
  1451. case SCREEN_OBJECT_NONE:
  1452. case SCREEN_OBJECT_SITE:
  1453. return CURSOR_UNIT;
  1454. case SCREEN_OBJECT_FRIEND_UNIT:
  1455. return choose_cursor_unit_group(pointingObjectRecno);
  1456. case SCREEN_OBJECT_UNIT_GROUP:
  1457. err_here(); // impossible to pointing at more than one unit
  1458. return CURSOR_UNIT_C;
  1459. case SCREEN_OBJECT_FRIEND_TOWN:
  1460. for( i = 1; i < arraySize; ++i)
  1461. {
  1462. Unit *unitPtr;
  1463. if( unit_array.is_deleted(i) || !(unitPtr = unit_array[i])->selected_flag )
  1464. continue;
  1465. // ###### begin Gilbert 18/10 ########//
  1466. if( unitPtr->race_id && unitPtr->rank_id == RANK_SOLDIER
  1467. && !unitPtr->skill.skill_id )
  1468. // ###### end Gilbert 18/10 ########//
  1469. return CURSOR_ASSIGN;
  1470. }
  1471. return CURSOR_UNIT_C;
  1472. case SCREEN_OBJECT_FRIEND_FIRM:
  1473. {
  1474. Firm *firmPtr = firm_array[pointingObjectRecno];
  1475. pointingObjectId = firmPtr->firm_id;
  1476. for( i = 1; i < arraySize; ++i)
  1477. {
  1478. Unit *unitPtr;
  1479. if( unit_array.is_deleted(i) || !(unitPtr = unit_array[i])->selected_flag )
  1480. continue;
  1481. // ##### begin Gilbert 22/10 #######//
  1482. // if( unitPtr->firm_can_assign(pointingObjectRecno) )
  1483. if( unit_can_assign_firm(i, pointingObjectRecno, nation_array.player_recno) )
  1484. return CURSOR_ASSIGN;
  1485. // ##### end Gilbert 22/10 #######//
  1486. }
  1487. return CURSOR_UNIT_C;
  1488. }
  1489. case SCREEN_OBJECT_ENEMY_UNIT:
  1490. case SCREEN_OBJECT_ENEMY_TOWN:
  1491. case SCREEN_OBJECT_ENEMY_FIRM:
  1492. return CURSOR_UNIT_O;
  1493. case SCREEN_OBJECT_WALL:
  1494. return CURSOR_DESTRUCT;
  1495. default:
  1496. err_here();
  1497. return CURSOR_UNIT;
  1498. }
  1499. }
  1500. case SCREEN_OBJECT_FRIEND_TOWN:
  1501. {
  1502. Town *townPtr = town_array[selectedObjectRecno];
  1503. switch( pointingObjectType)
  1504. {
  1505. case SCREEN_OBJECT_NONE:
  1506. case SCREEN_OBJECT_WALL:
  1507. case SCREEN_OBJECT_SITE:
  1508. return CURSOR_C_TOWN;
  1509. case SCREEN_OBJECT_FRIEND_UNIT:
  1510. case SCREEN_OBJECT_UNIT_GROUP:
  1511. return CURSOR_C_TOWN_C;
  1512. case SCREEN_OBJECT_FRIEND_FIRM:
  1513. {
  1514. Firm *pFirm = firm_array[pointingObjectRecno];
  1515. int centerX = (pFirm->loc_x1 + pFirm->loc_x2 +1)*ZOOM_LOC_WIDTH/2 - World::view_top_x;
  1516. int centerY = (pFirm->loc_y1 + pFirm->loc_y2 +1)*ZOOM_LOC_HEIGHT/2 - World::view_top_y;
  1517. if(m.points_distance( mouse.cur_x, mouse.cur_y, centerX+ZOOM_X1, centerY+ZOOM_Y1) <= 11
  1518. && townPtr->can_toggle_firm_link(pointingObjectRecno) )
  1519. {
  1520. return CURSOR_ON_LINK;
  1521. }
  1522. }
  1523. return CURSOR_C_TOWN_C;
  1524. case SCREEN_OBJECT_FRIEND_TOWN:
  1525. if( selectedObjectRecno != pointingObjectRecno )
  1526. {
  1527. // check if the cursor is pointing at the middle of the town
  1528. Town *pTown = town_array[pointingObjectRecno];
  1529. int centerX = (pTown->loc_x1 + pTown->loc_x2 +1)*ZOOM_LOC_WIDTH/2 - World::view_top_x;
  1530. int centerY = (pTown->loc_y1 + pTown->loc_y2 +1)*ZOOM_LOC_HEIGHT/2 - World::view_top_y;
  1531. if(m.points_distance( mouse.cur_x, mouse.cur_y, centerX+ZOOM_X1, centerY+ZOOM_Y1) <= 11
  1532. && townPtr->can_migrate(pointingObjectRecno) )
  1533. {
  1534. return CURSOR_ON_LINK;
  1535. }
  1536. }
  1537. return CURSOR_C_TOWN_C;
  1538. case SCREEN_OBJECT_ENEMY_UNIT:
  1539. case SCREEN_OBJECT_ENEMY_TOWN:
  1540. return CURSOR_C_TOWN_O;
  1541. case SCREEN_OBJECT_ENEMY_FIRM:
  1542. {
  1543. Firm *pFirm = firm_array[pointingObjectRecno];
  1544. int centerX = (pFirm->loc_x1 + pFirm->loc_x2 +1)*ZOOM_LOC_WIDTH/2 - World::view_top_x;
  1545. int centerY = (pFirm->loc_y1 + pFirm->loc_y2 +1)*ZOOM_LOC_HEIGHT/2 - World::view_top_y;
  1546. if(m.points_distance( mouse.cur_x, mouse.cur_y, centerX+ZOOM_X1, centerY+ZOOM_Y1) <= 11
  1547. && townPtr->can_toggle_firm_link(pointingObjectRecno) )
  1548. {
  1549. return CURSOR_ON_LINK;
  1550. }
  1551. }
  1552. return CURSOR_C_TOWN_O;
  1553. default:
  1554. err_here();
  1555. return CURSOR_C_TOWN;
  1556. }
  1557. }
  1558. case SCREEN_OBJECT_ENEMY_TOWN:
  1559. {
  1560. Town *townPtr = town_array[selectedObjectRecno];
  1561. switch( pointingObjectType)
  1562. {
  1563. case SCREEN_OBJECT_NONE:
  1564. case SCREEN_OBJECT_WALL:
  1565. case SCREEN_OBJECT_SITE:
  1566. return CURSOR_O_TOWN;
  1567. case SCREEN_OBJECT_FRIEND_UNIT:
  1568. case SCREEN_OBJECT_UNIT_GROUP:
  1569. case SCREEN_OBJECT_FRIEND_TOWN:
  1570. return CURSOR_O_TOWN_C;
  1571. case SCREEN_OBJECT_FRIEND_FIRM:
  1572. return CURSOR_O_TOWN_C;
  1573. case SCREEN_OBJECT_ENEMY_UNIT:
  1574. case SCREEN_OBJECT_ENEMY_TOWN:
  1575. case SCREEN_OBJECT_ENEMY_FIRM:
  1576. return CURSOR_O_TOWN_O;
  1577. default:
  1578. err_here();
  1579. return CURSOR_O_TOWN;
  1580. }
  1581. }
  1582. case SCREEN_OBJECT_FRIEND_FIRM:
  1583. {
  1584. Firm *firmPtr = firm_array[selectedObjectRecno];
  1585. switch( pointingObjectType)
  1586. {
  1587. case SCREEN_OBJECT_NONE:
  1588. case SCREEN_OBJECT_WALL:
  1589. case SCREEN_OBJECT_SITE:
  1590. return CURSOR_C_FIRM;
  1591. case SCREEN_OBJECT_FRIEND_UNIT:
  1592. case SCREEN_OBJECT_UNIT_GROUP:
  1593. return CURSOR_C_FIRM_C;
  1594. case SCREEN_OBJECT_FRIEND_TOWN:
  1595. {
  1596. Town *pTown = town_array[pointingObjectRecno];
  1597. int centerX = (pTown->loc_x1 + pTown->loc_x2 +1)*ZOOM_LOC_WIDTH/2 - World::view_top_x;
  1598. int centerY = (pTown->loc_y1 + pTown->loc_y2 +1)*ZOOM_LOC_HEIGHT/2 - World::view_top_y;
  1599. if(m.points_distance( mouse.cur_x, mouse.cur_y, centerX+ZOOM_X1, centerY+ZOOM_Y1) <= 11
  1600. && firmPtr->can_toggle_town_link() )
  1601. {
  1602. return CURSOR_ON_LINK;
  1603. }
  1604. }
  1605. return CURSOR_C_FIRM_C;
  1606. case SCREEN_OBJECT_FRIEND_FIRM:
  1607. if( selectedObjectRecno != pointingObjectRecno )
  1608. {
  1609. Firm *pFirm = firm_array[pointingObjectRecno];
  1610. int centerX = (pFirm->loc_x1 + pFirm->loc_x2 +1)*ZOOM_LOC_WIDTH/2 - World::view_top_x;
  1611. int centerY = (pFirm->loc_y1 + pFirm->loc_y2 +1)*ZOOM_LOC_HEIGHT/2 - World::view_top_y;
  1612. if(m.points_distance( mouse.cur_x, mouse.cur_y, centerX+ZOOM_X1, centerY+ZOOM_Y1) <= 11
  1613. && firmPtr->can_toggle_firm_link(pointingObjectRecno) )
  1614. {
  1615. return CURSOR_ON_LINK;
  1616. }
  1617. }
  1618. return CURSOR_C_FIRM_C;
  1619. case SCREEN_OBJECT_ENEMY_UNIT:
  1620. return CURSOR_C_FIRM_O;
  1621. case SCREEN_OBJECT_ENEMY_TOWN:
  1622. {
  1623. Town *pTown = town_array[pointingObjectRecno];
  1624. int centerX = (pTown->loc_x1 + pTown->loc_x2 +1)*ZOOM_LOC_WIDTH/2 - World::view_top_x;
  1625. int centerY = (pTown->loc_y1 + pTown->loc_y2 +1)*ZOOM_LOC_HEIGHT/2 - World::view_top_y;
  1626. if(m.points_distance( mouse.cur_x, mouse.cur_y, centerX+ZOOM_X1, centerY+ZOOM_Y1) <= 11
  1627. && firmPtr->can_toggle_town_link() )
  1628. {
  1629. return CURSOR_ON_LINK;
  1630. }
  1631. }
  1632. return CURSOR_C_FIRM_O;
  1633. case SCREEN_OBJECT_ENEMY_FIRM:
  1634. {
  1635. Firm *pFirm = firm_array[pointingObjectRecno];
  1636. int centerX = (pFirm->loc_x1 + pFirm->loc_x2 +1)*ZOOM_LOC_WIDTH/2 - World::view_top_x;
  1637. int centerY = (pFirm->loc_y1 + pFirm->loc_y2 +1)*ZOOM_LOC_HEIGHT/2 - World::view_top_y;
  1638. if(m.points_distance( mouse.cur_x, mouse.cur_y, centerX+ZOOM_X1, centerY+ZOOM_Y1) <= 11
  1639. && firmPtr->can_toggle_firm_link(pointingObjectRecno) )
  1640. {
  1641. return CURSOR_ON_LINK;
  1642. }
  1643. }
  1644. return CURSOR_C_FIRM_O;
  1645. default:
  1646. err_here();
  1647. return CURSOR_C_FIRM;
  1648. }
  1649. }
  1650. case SCREEN_OBJECT_ENEMY_FIRM:
  1651. {
  1652. switch( pointingObjectType)
  1653. {
  1654. case SCREEN_OBJECT_NONE:
  1655. case SCREEN_OBJECT_WALL:
  1656. case SCREEN_OBJECT_SITE:
  1657. return CURSOR_O_FIRM;
  1658. case SCREEN_OBJECT_FRIEND_UNIT:
  1659. case SCREEN_OBJECT_UNIT_GROUP:
  1660. case SCREEN_OBJECT_FRIEND_FIRM:
  1661. return CURSOR_O_FIRM_C;
  1662. case SCREEN_OBJECT_FRIEND_TOWN:
  1663. return CURSOR_O_FIRM_C;
  1664. case SCREEN_OBJECT_ENEMY_UNIT:
  1665. case SCREEN_OBJECT_ENEMY_TOWN:
  1666. case SCREEN_OBJECT_ENEMY_FIRM:
  1667. return CURSOR_O_FIRM_O;
  1668. default:
  1669. err_here();
  1670. return CURSOR_O_TOWN;
  1671. }
  1672. }
  1673. default:
  1674. err_here();
  1675. return CURSOR_NORMAL;
  1676. }
  1677. }
  1678. else
  1679. {
  1680. // ------ outside zoom area depend on selected object ------//
  1681. switch(selectedObjectType)
  1682. {
  1683. case SCREEN_OBJECT_NONE:
  1684. case SCREEN_OBJECT_WALL:
  1685. case SCREEN_OBJECT_SITE:
  1686. case SCREEN_OBJECT_ENEMY_UNIT:
  1687. return CURSOR_NORMAL;
  1688. case SCREEN_OBJECT_FRIEND_UNIT:
  1689. case SCREEN_OBJECT_UNIT_GROUP:
  1690. case SCREEN_OBJECT_SPY_UNIT:
  1691. return CURSOR_UNIT;
  1692. case SCREEN_OBJECT_FRIEND_TOWN:
  1693. return CURSOR_C_TOWN;
  1694. case SCREEN_OBJECT_ENEMY_TOWN:
  1695. return CURSOR_O_TOWN;
  1696. case SCREEN_OBJECT_FRIEND_FIRM:
  1697. return CURSOR_C_FIRM;
  1698. case SCREEN_OBJECT_ENEMY_FIRM:
  1699. return CURSOR_O_FIRM;
  1700. default:
  1701. err_here();
  1702. return CURSOR_NORMAL;
  1703. }
  1704. }
  1705. }
  1706. }
  1707. // ---------- End of function Power::choose_cursor --------//
  1708. // ---------- Begin of function Power::choose_cursor_units --------//
  1709. //
  1710. int Power::choose_cursor_units(short selectedUnitRecno, short pointingUnitRecno)
  1711. {
  1712. Unit *u1Ptr = unit_array[selectedUnitRecno];
  1713. Unit *u2Ptr = unit_array[pointingUnitRecno];
  1714. int selectedUnitId = u1Ptr->unit_id;
  1715. int pointingUnitId = u2Ptr->unit_id;
  1716. UnitInfo *u1 = unit_res[selectedUnitId];
  1717. UnitInfo *u2 = unit_res[pointingUnitId];
  1718. if(u1 && u2)
  1719. {
  1720. // ------- detect ship that can carry land unit -------//
  1721. if( u1->mobile_type == UNIT_LAND &&
  1722. u2 && u2->carry_unit_capacity > 0)
  1723. {
  1724. return CURSOR_ASSIGN;
  1725. }
  1726. else if( pointingUnitId == UNIT_EXPLOSIVE_CART && // check trigger explosive cart
  1727. u1Ptr->max_attack_range() > 1)
  1728. {
  1729. return CURSOR_TRIGGER_EXPLODE;
  1730. }
  1731. else if( u1->vehicle_id == pointingUnitId && // can ride on
  1732. u1->solider_id != 0) // make sure u1 is a rider, not a riding unit
  1733. {
  1734. return CURSOR_ASSIGN;
  1735. }
  1736. }
  1737. return CURSOR_UNIT_C;
  1738. }
  1739. // ---------- End of function Power::choose_cursor_units --------//
  1740. // ---------- Begin of function Power::choose_cursor_unit_group --------//
  1741. //
  1742. int Power::choose_cursor_unit_group(short pointingUnitRecno)
  1743. {
  1744. int pointingUnitId = unit_array[pointingUnitRecno]->unit_id;
  1745. // ----- assume all selected unit are owned by the player ----//
  1746. UnitInfo *u2 = unit_res[pointingUnitId];
  1747. if(u2)
  1748. {
  1749. // ------- detect ship that can carry land unit -------//
  1750. if( u2->carry_unit_capacity > 0)
  1751. {
  1752. // if any land unit in the selected array
  1753. int s = unit_array.size();
  1754. for(int i=1; i <= s; ++i)
  1755. {
  1756. if( !unit_array.is_deleted(i) && unit_array[i]->selected_flag)
  1757. {
  1758. UnitInfo *u1 = unit_res[unit_array[i]->unit_id];
  1759. if( u1->mobile_type == UNIT_LAND)
  1760. return CURSOR_ASSIGN;
  1761. }
  1762. }
  1763. }
  1764. else if( pointingUnitId == UNIT_EXPLOSIVE_CART )
  1765. {
  1766. // if any land unit in the selected array
  1767. int s = unit_array.size();
  1768. for(int i=1; i <= s; ++i)
  1769. {
  1770. Unit *unitPtr;
  1771. if( !unit_array.is_deleted(i) && (unitPtr = unit_array[i])->selected_flag)
  1772. {
  1773. if( unitPtr->max_attack_range() > 1)
  1774. return CURSOR_TRIGGER_EXPLODE;
  1775. }
  1776. }
  1777. }
  1778. else
  1779. {
  1780. // see if pointing unit is vehicle of any of the selected unit
  1781. int s = unit_array.size();
  1782. for(int i=1; i <= s; ++i)
  1783. {
  1784. if( !unit_array.is_deleted(i) && unit_array[i]->selected_flag)
  1785. {
  1786. UnitInfo *u1 = unit_res[unit_array[i]->unit_id];
  1787. if( u1->vehicle_id == pointingUnitId)
  1788. return CURSOR_ASSIGN;
  1789. }
  1790. }
  1791. //------- check other relationship here -------//
  1792. }
  1793. }
  1794. return CURSOR_UNIT_C;
  1795. }
  1796. // ---------- End of function Power::choose_cursor_unit_group --------//
  1797. // ---------- Begin of function Power::find_selected_type --------//
  1798. //
  1799. ScreenObjectType Power::find_selected_type( short *selectedRecno)
  1800. {
  1801. short dummyId;
  1802. if( selectedRecno == NULL)
  1803. selectedRecno = &dummyId;
  1804. if( unit_array.selected_recno )
  1805. {
  1806. // -------- check selected single unit ---------//
  1807. if( unit_array.selected_count == 1)
  1808. {
  1809. Unit *unitPtr = unit_array[*selectedRecno = unit_array.selected_recno];
  1810. return unitPtr->nation_recno == nation_array.player_recno ?
  1811. SCREEN_OBJECT_FRIEND_UNIT :
  1812. (unitPtr->true_nation_recno() == nation_array.player_recno ?
  1813. SCREEN_OBJECT_SPY_UNIT : SCREEN_OBJECT_ENEMY_UNIT);
  1814. }
  1815. // -------- check selected a group of units ---------//
  1816. if( unit_array.selected_count > 1)
  1817. {
  1818. *selectedRecno = unit_array.selected_recno;
  1819. return SCREEN_OBJECT_UNIT_GROUP;
  1820. }
  1821. }
  1822. // -------- check selected a firm ---------//
  1823. if( firm_array.selected_recno )
  1824. {
  1825. Firm *firmPtr = firm_array[*selectedRecno = firm_array.selected_recno];
  1826. return firmPtr->nation_recno == nation_array.player_recno ?
  1827. SCREEN_OBJECT_FRIEND_FIRM : SCREEN_OBJECT_ENEMY_FIRM;
  1828. }
  1829. // -------- check selected a town ---------//
  1830. if( town_array.selected_recno )
  1831. {
  1832. Town *townPtr = town_array[*selectedRecno = town_array.selected_recno];
  1833. return townPtr->nation_recno == nation_array.player_recno ?
  1834. SCREEN_OBJECT_FRIEND_TOWN : SCREEN_OBJECT_ENEMY_TOWN;
  1835. }
  1836. // -------- check selected a site ---------//
  1837. if( site_array.selected_recno )
  1838. {
  1839. Site *sitePtr = site_array[*selectedRecno = site_array.selected_recno];
  1840. return SCREEN_OBJECT_SITE;
  1841. }
  1842. // -------- check selected a wall ---------//
  1843. if( wall_res.selected_x_loc >= 0 && wall_res.selected_y_loc >= 0)
  1844. {
  1845. *selectedRecno = world.get_loc(wall_res.selected_x_loc, wall_res.selected_y_loc)->power_nation_recno;
  1846. return SCREEN_OBJECT_WALL;
  1847. }
  1848. return SCREEN_OBJECT_NONE;
  1849. }
  1850. // ---------- End of function Power::find_selected_type --------//
  1851. // ---------- Begin of function Power::find_pointing_type --------//
  1852. //
  1853. ScreenObjectType Power::find_pointing_type( Location *locPtr, short *pointingRecno)
  1854. {
  1855. short dummyId;
  1856. if( pointingRecno == NULL)
  1857. pointingRecno = &dummyId;
  1858. // ------- check pointing at unit, always check air unit first -------//
  1859. if( locPtr->has_unit( UNIT_AIR ) )
  1860. {
  1861. Unit *unitPtr = unit_array[*pointingRecno = locPtr->unit_recno(UNIT_AIR)];
  1862. return unitPtr->nation_recno == nation_array.player_recno ?
  1863. SCREEN_OBJECT_FRIEND_UNIT : SCREEN_OBJECT_ENEMY_UNIT;
  1864. }
  1865. if( locPtr->has_unit( UNIT_LAND ) )
  1866. {
  1867. Unit *unitPtr = unit_array[*pointingRecno = locPtr->unit_recno(UNIT_LAND)];
  1868. return unitPtr->nation_recno == nation_array.player_recno ?
  1869. SCREEN_OBJECT_FRIEND_UNIT : SCREEN_OBJECT_ENEMY_UNIT;
  1870. }
  1871. if( locPtr->has_unit( UNIT_SEA ) )
  1872. {
  1873. Unit *unitPtr = unit_array[*pointingRecno = locPtr->unit_recno(UNIT_SEA)];
  1874. return unitPtr->nation_recno == nation_array.player_recno ?
  1875. SCREEN_OBJECT_FRIEND_UNIT : SCREEN_OBJECT_ENEMY_UNIT;
  1876. }
  1877. // -------- check pointing at firm ---------//
  1878. if( locPtr->is_firm() )
  1879. {
  1880. Firm *firmPtr = firm_array[*pointingRecno = locPtr->firm_recno()];
  1881. return firmPtr->nation_recno == nation_array.player_recno ?
  1882. SCREEN_OBJECT_FRIEND_FIRM : SCREEN_OBJECT_ENEMY_FIRM;
  1883. }
  1884. // ------- check pointing at town ---------//
  1885. if( locPtr->is_town() )
  1886. {
  1887. Town *townPtr = town_array[*pointingRecno = locPtr->town_recno()];
  1888. return townPtr->nation_recno == nation_array.player_recno ?
  1889. SCREEN_OBJECT_FRIEND_TOWN : SCREEN_OBJECT_ENEMY_TOWN;
  1890. }
  1891. // -------- check pointing a site ---------//
  1892. if( locPtr->has_site() )
  1893. {
  1894. Site *sitePtr = site_array[*pointingRecno = locPtr->site_recno()];
  1895. return SCREEN_OBJECT_SITE;
  1896. }
  1897. // -------- check pointing a wall ---------//
  1898. if( locPtr->is_wall() )
  1899. {
  1900. *pointingRecno = locPtr->power_nation_recno;
  1901. return SCREEN_OBJECT_WALL;
  1902. }
  1903. return SCREEN_OBJECT_NONE;
  1904. }
  1905. // ---------- End of function Power::find_pointing_type --------//
  1906. // ###### begin Gilbert 22/10 #######//
  1907. // ---------- Begin of function Power::unit_can_assign_firm --------//
  1908. int Power::unit_can_assign_firm(int unitRecno, int firmRecno, int ownNationRecno)
  1909. {
  1910. if(!ownNationRecno || !unitRecno || !firmRecno )
  1911. return 0;
  1912. if( unit_array.is_deleted(unitRecno) )
  1913. return 0;
  1914. Unit *unitPtr = unit_array[unitRecno];
  1915. if( firm_array.is_deleted(firmRecno) )
  1916. return 0;
  1917. Firm *firmPtr = firm_array[firmRecno];
  1918. int rc = unitPtr->firm_can_assign(firmRecno);
  1919. if( !rc )
  1920. return 0;
  1921. //----------------------------------------//
  1922. // If this is a spy, then he can only be
  1923. // assigned to an enemy firm when there is
  1924. // space for the unit.
  1925. //----------------------------------------//
  1926. if( ownNationRecno != firmPtr->nation_recno )
  1927. {
  1928. switch(rc)
  1929. {
  1930. case 1: // assign as worker
  1931. if( firmPtr->worker_count == MAX_WORKER )
  1932. return 0;
  1933. break;
  1934. case 2: // assign as overseer
  1935. if( firmPtr->overseer_recno )
  1936. return 0;
  1937. break;
  1938. case 3: // assign as construction unit
  1939. if( firmPtr->builder_recno )
  1940. return 0;
  1941. break;
  1942. }
  1943. }
  1944. return rc;
  1945. }
  1946. // ---------- End of function Power::unit_can_assign_firm --------//
  1947. // ###### end Gilbert 22/10 #######//
  1948. //### begin alex 19/3 ###//
  1949. //---------- Begin of function Power::select_active_unit --------//
  1950. // choose the most suitable unit to be the active unit
  1951. //
  1952. // For this version and the situation, unit with ability to attack is
  1953. // used instead of selecting the first unit in the array
  1954. //
  1955. // The full version should consider: 1) whether the unit is human,
  1956. // 2) can attack, 3) mobile type, etc. Or divide the unit once more
  1957. // before calling functions in unit_array
  1958. //
  1959. short Power::select_active_unit(short *selectedArray, short selectedCount)
  1960. {
  1961. Unit *unitPtr;
  1962. for(short i=0; i<selectedCount; ++i)
  1963. {
  1964. err_when(unit_array.is_deleted(selectedArray[i]));
  1965. unitPtr = unit_array[selectedArray[i]];
  1966. if(unitPtr->can_attack())
  1967. return selectedArray[i];
  1968. }
  1969. //------ return the first one if none of them can attack --------//
  1970. return selectedArray[0];
  1971. }
  1972. //---------- End of function Power::select_active_unit --------//
  1973. //#### end alex 19/3 ####//