OSERES.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  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 : OSERES.CPP
  21. // Description : Sound resource
  22. // search a sound effect id from subject verb object
  23. // pass the id to se_ctrl.request to trigger the sound effect
  24. // Owner : Gilbert
  25. #include <OSERES.h>
  26. #include <OSE.h>
  27. #include <OGAMESET.h>
  28. #include <OWORLD.h>
  29. #include <OCONFIG.h>
  30. #include <string.h>
  31. #include <stdlib.h>
  32. // ---------- Define constant ----------//
  33. #define SERES_DB "SOUNDRES"
  34. unsigned long SERes::last_select_time = 0;
  35. unsigned long SERes::last_command_time = 0;
  36. unsigned long SERes::select_sound_length = 600; // time between successive select sound
  37. // --------- begin of function SEInfo::match ----------//
  38. int SEInfo::match(char subjectType, short subjectId, char *act,
  39. char objectType, short objectId)
  40. {
  41. // object_type == -1, match all object type
  42. // object_id == -1, match all object id of that type
  43. return subject_type == subjectType &&
  44. (subject_id == -1 || subject_id == subjectId) &&
  45. strncmp(action, act, VERB_LEN )== 0 &&
  46. (object_type == -1 || (object_type == objectType &&
  47. (object_id == -1 || object_id == objectId)));
  48. }
  49. // --------- end of function SEInfo::match ----------//
  50. // --------- begin of function SERes::SERes ----------//
  51. SERes::SERes()
  52. {
  53. init_flag = 0;
  54. se_array_count = 0;
  55. se_array = NULL;
  56. se_index_count = 0;
  57. se_index_array = NULL;
  58. type_index_count = 0;
  59. type_index_array = NULL;
  60. }
  61. // --------- end of function SERes::SERes ----------//
  62. // --------- begin of function SERes::~SERes ----------//
  63. SERes::~SERes()
  64. {
  65. deinit();
  66. }
  67. // --------- end of function SERes::~SERes ----------//
  68. // --------- begin of function SERes::init1 ----------//
  69. void SERes::init1()
  70. {
  71. deinit();
  72. seed = m.get_time();
  73. load_info();
  74. sort_info();
  75. build_index();
  76. init_flag = 1;
  77. }
  78. // --------- end of function SERes::init1 ----------//
  79. // --------- begin of function SERes::init2 ----------//
  80. // called after se_ctrl is init
  81. void SERes::init2(SECtrl *seCtrl)
  82. {
  83. err_when( !seCtrl || !seCtrl->init_flag );
  84. err_when( init_flag == 0 );
  85. se_output = seCtrl;
  86. int i;
  87. SEInfo *seInfo;
  88. for(i = 0, seInfo = se_array; i < se_array_count; ++i, ++seInfo )
  89. {
  90. seInfo->effect_id = seCtrl->search_effect_id(seInfo->file_name);
  91. }
  92. init_flag = 2;
  93. }
  94. // --------- end of function SERes::init2 ----------//
  95. // --------- begin of function SERes::deinit ----------//
  96. void SERes::deinit()
  97. {
  98. if( init_flag )
  99. {
  100. mem_del(se_array);
  101. se_array = NULL;
  102. se_array_count = 0;
  103. mem_del(se_index_array);
  104. se_index_array = NULL;
  105. se_index_count = 0;
  106. mem_del(type_index_array);
  107. type_index_array = NULL;
  108. type_index_count = 0;
  109. init_flag = 0;
  110. }
  111. }
  112. // --------- end of function SERes::deinit ----------//
  113. // --------- begin of function SERes::load_info ----------//
  114. void SERes::load_info()
  115. {
  116. SERec *seRec;
  117. SEInfo *seInfo;
  118. int i;
  119. Database *dbSE = game_set.open_db(SERES_DB);
  120. se_array_count = dbSE->rec_count();
  121. se_array = (SEInfo *)mem_add(sizeof(SEInfo) * se_array_count);
  122. memset( se_array, 0, sizeof(SEInfo) * se_array_count );
  123. for( i = 0; i < se_array_count; ++i )
  124. {
  125. seRec = (SERec *) dbSE->read(i+1);
  126. seInfo = se_array+i;
  127. // ------- copy subject ---------//
  128. seInfo->subject_type = seRec->subject_type;
  129. seInfo->subject_id = m.atoi(seRec->subject_id, seRec->RECNO_LEN);
  130. // -------- copy verb ---------//
  131. memcpy( seInfo->action, seRec->action, seRec->VERB_LEN );
  132. seInfo->action[seInfo->VERB_LEN] = '\0';
  133. m.rtrim( seInfo->action );
  134. // --------- copy object ---------//
  135. if( seRec->object_type == ' ' || seRec->object_type == '\0')
  136. {
  137. seInfo->object_type = 0;
  138. seInfo->object_id = 0;
  139. }
  140. else if( seRec->object_type == '*' )
  141. {
  142. seInfo->object_type = -1; // all object
  143. seInfo->object_id = -1;
  144. }
  145. else
  146. {
  147. seInfo->object_type = seRec->object_type;
  148. if( seRec->object_id[0] != '*' )
  149. seInfo->object_id = m.atoi(seRec->object_id, seRec->RECNO_LEN);
  150. else
  151. seInfo->object_id = -1; // all of the objectType
  152. }
  153. // -------- copy out frame ---------//
  154. seInfo->out_frame = m.atoi(seRec->out_frame, seRec->OUT_FRAME_LEN);
  155. err_when(seInfo->out_frame <= 0);
  156. // -------- copy file name --------//
  157. memcpy(seInfo->file_name, seRec->file_name, seRec->FILE_NAME_LEN);
  158. seInfo->file_name[seInfo->FILE_NAME_LEN] = '\0';
  159. m.rtrim(seInfo->file_name);
  160. seInfo->effect_id = 0;
  161. }
  162. }
  163. // --------- end of function SERes::load_info ----------//
  164. // --------- begin of function SERes::sort_info --------//
  165. static int seinfo_cmp(const void *r1, const void *r2)
  166. {
  167. return memcmp(r1, r2, sizeof(SEInfo));
  168. }
  169. void SERes::sort_info()
  170. {
  171. // notice object_id -1 are put after any other object_id
  172. qsort(se_array, se_array_count, sizeof(SEInfo), seinfo_cmp);
  173. }
  174. // --------- end of function SERes::sort_info --------//
  175. // --------- begin of function SERes::build_index -------//
  176. // build index on (subject_type, subject_id)
  177. void SERes::build_index()
  178. {
  179. // ---------- first pass, count the size of index ---------//
  180. int i,j,k;
  181. SEInfo *seInfo;
  182. char lastType = -1;
  183. short lastId;
  184. type_index_count = 0;
  185. se_index_count = 0;
  186. for(i = 0, seInfo = se_array; i < se_array_count; ++i, ++seInfo)
  187. {
  188. if( lastType != seInfo->subject_type)
  189. {
  190. type_index_count++;
  191. se_index_count++;
  192. lastType = seInfo->subject_type;
  193. lastId = seInfo->subject_id;
  194. }
  195. else if( lastId != seInfo->subject_id)
  196. {
  197. se_index_count++;
  198. lastId = seInfo->subject_id;
  199. }
  200. }
  201. // --------- allocate memory for index ----------//
  202. SEInfoIndex *seIndex = se_index_array = (SEInfoIndex *)
  203. mem_resize( se_index_array, sizeof(SEInfoIndex) * se_index_count);
  204. memset( se_index_array, 0, sizeof(SEInfoIndex) * se_index_count);
  205. SETypeIndex *typeIndex = type_index_array = (SETypeIndex *)
  206. mem_resize( type_index_array, sizeof(SETypeIndex) * type_index_count);
  207. memset( type_index_array, 0, sizeof(SETypeIndex) * type_index_count);
  208. // ---------- pass 2, build indices -----------//
  209. seIndex--; // move one step backward
  210. typeIndex--;
  211. j = -1;
  212. k = -1;
  213. lastType = -1;
  214. for(i = 0, seInfo = se_array; i < se_array_count; ++i, ++seInfo)
  215. {
  216. if( lastType != seInfo->subject_type)
  217. {
  218. // ----------- new (type,Id) ---------//
  219. ++seIndex;
  220. ++j;
  221. seIndex->subject_type = seInfo->subject_type;
  222. seIndex->subject_id = seInfo->subject_id;
  223. seIndex->start_rec = seIndex->end_rec = i;
  224. // ----------- new type ---------//
  225. ++typeIndex;
  226. ++k;
  227. typeIndex->subject_type = seInfo->subject_type;
  228. typeIndex->start_rec = typeIndex->end_rec = j;
  229. lastType = seInfo->subject_type;
  230. lastId = seInfo->subject_id;
  231. }
  232. else
  233. {
  234. err_when(typeIndex < type_index_array); // must not enter here for the first time
  235. if( lastId != seInfo->subject_id)
  236. {
  237. // ----------- new (type,Id) ---------//
  238. ++seIndex;
  239. ++j;
  240. seIndex->subject_type = seInfo->subject_type;
  241. seIndex->subject_id = seInfo->subject_id;
  242. seIndex->start_rec = i;
  243. seIndex->end_rec = i;
  244. lastId = seInfo->subject_id;
  245. }
  246. else
  247. {
  248. err_when(seIndex < se_index_array);
  249. seIndex->end_rec = i;
  250. }
  251. typeIndex->end_rec = j;
  252. }
  253. }
  254. }
  255. // --------- end of function SERes::build_index -------//
  256. // --------- begin of function SERes::scan ----------//
  257. // search the SEInfo whose subject, action and object match
  258. // <char> subjectType type of subject 'S'= sprite,
  259. // 'U'=unit, 'R'=race, 'F'=firm, 'T'=town
  260. // <short> subjectId sprite_id, unit_id, race_id or firm_id ...
  261. // <char *> act name of the action, first four chars are significant
  262. // [char] objectType type of object 'S'= sprite,
  263. // 'U'=unit, 'R'=race, 'F'=firm, 'T'=town
  264. // default : 0 (none)
  265. // [short] objectId sprite_id, unit_id, race_id or firm_id ...
  266. // default : 0 (none)
  267. //
  268. // return NULL if not found
  269. //
  270. SEInfo* SERes::scan(char subjectType, short subjectId, char *act,
  271. char objectType, short objectId, int findFirst)
  272. {
  273. err_when(!init_flag);
  274. int startRec, endRec, i;
  275. SETypeIndex *typeIndex;
  276. SEInfoIndex *seIndex;
  277. SEInfo *seInfo;
  278. // ---------- search the type_index_array ---------//
  279. int foundFlag = 0;
  280. for( i = 0, typeIndex = type_index_array; i < type_index_count; ++i, ++typeIndex)
  281. {
  282. if( subjectType == typeIndex->subject_type)
  283. {
  284. startRec = typeIndex->start_rec;
  285. endRec = typeIndex->end_rec;
  286. foundFlag = 1;
  287. break;
  288. }
  289. }
  290. if( !foundFlag )
  291. return NULL;
  292. // ---------- search the se_index_array ---------//
  293. foundFlag = 0;
  294. for( i = startRec, seIndex = se_index_array + startRec; i <= endRec;
  295. ++i, ++seIndex)
  296. {
  297. if( subjectId == seIndex->subject_id && subjectType == seIndex->subject_type)
  298. {
  299. startRec = seIndex->start_rec;
  300. endRec = seIndex->end_rec;
  301. foundFlag = 1;
  302. break;
  303. }
  304. }
  305. if( !foundFlag ) // not found
  306. return NULL;
  307. // ----------- search the se_array ----------//
  308. for(i = startRec, seInfo = se_array + startRec; i <= endRec;
  309. ++i, ++seInfo)
  310. {
  311. if( seInfo->match(subjectType, subjectId, act, objectType, objectId) )
  312. break;
  313. }
  314. if( i <= endRec ) // found
  315. {
  316. if( findFirst )
  317. return seInfo;
  318. int found = 1;
  319. SEInfo *retSEInfo = seInfo;
  320. for( ++i, ++seInfo ; i <= endRec && found <= 4 &&
  321. seInfo->match(subjectType, subjectId, act, objectType, objectId);
  322. ++i, ++seInfo )
  323. {
  324. ++found;
  325. if( random(found+1) == 0)
  326. retSEInfo = seInfo;
  327. }
  328. return retSEInfo;
  329. }
  330. return NULL;
  331. }
  332. // --------- end of function SERes::scan ----------//
  333. // --------- begin of function SERes::scan_id ----------//
  334. short SERes::scan_id(char subjectType, short subjectId, char *act,
  335. char objectType, short objectId, int findFirst)
  336. {
  337. SEInfo *seInfo;
  338. if( (seInfo = scan(subjectType, subjectId, act, objectType, objectId, findFirst))
  339. != NULL)
  340. return seInfo->effect_id;
  341. return 0;
  342. }
  343. // --------- end of function SERes::scan_id ----------//
  344. // --------- begin of function SERes::operator[] ----------//
  345. SEInfo* SERes::operator[] (int i)
  346. {
  347. err_when(!init_flag || i <= 0 || i > se_array_count);
  348. return se_array + i - 1;
  349. }
  350. // --------- end of function SERes::operator[] ----------//
  351. // --------- begin of function SERes::sound ----------//
  352. void SERes::sound(short xLoc, short yLoc, short frame,
  353. char subjectType,short subjectId, char *action, char objectType,short objectId)
  354. {
  355. //### begin trevor 20/8 ###//
  356. if( !config.sound_effect_flag )
  357. return;
  358. //### end trevor 20/8 ###//
  359. short relXLoc = xLoc - (world.zoom_matrix->top_x_loc + world.zoom_matrix->disp_x_loc/2);
  360. short relYLoc = yLoc - (world.zoom_matrix->top_y_loc + world.zoom_matrix->disp_y_loc/2);
  361. PosVolume posv(relXLoc, relYLoc);
  362. RelVolume relVolume( posv );
  363. if( !config.pan_control )
  364. relVolume.ds_pan = 0;
  365. SEInfo *seInfo;
  366. if( relVolume.rel_vol < 5)
  367. return;
  368. if( (seInfo=scan(subjectType, subjectId, action, objectType, objectId))
  369. != NULL && frame == seInfo->out_frame)
  370. {
  371. se_output->request(seInfo->effect_id, relVolume );
  372. }
  373. }
  374. // --------- end of function SERes::sound ----------//
  375. // --------- begin of function SERes::far_sound ----------//
  376. //
  377. // as same as far_sound, but no cut_off volume
  378. // usually used in acknowlege voice
  379. //
  380. void SERes::far_sound(short xLoc, short yLoc, short frame,
  381. char subjectType,short subjectId, char *action, char objectType,short objectId)
  382. {
  383. //### begin trevor 20/8 ###//
  384. if( !config.sound_effect_flag )
  385. return;
  386. //### end trevor 20/8 ###//
  387. short relXLoc = xLoc - (world.zoom_matrix->top_x_loc + world.zoom_matrix->disp_x_loc/2);
  388. short relYLoc = yLoc - (world.zoom_matrix->top_y_loc + world.zoom_matrix->disp_y_loc/2);
  389. PosVolume posv(relXLoc, relYLoc);
  390. RelVolume relVolume( posv, 200, MAX_MAP_WIDTH );
  391. if( !config.pan_control )
  392. relVolume.ds_pan = 0;
  393. SEInfo *seInfo;
  394. if( relVolume.rel_vol < 80)
  395. relVolume.rel_vol = 80;
  396. if( (seInfo=scan(subjectType, subjectId, action, objectType, objectId))
  397. != NULL && frame == seInfo->out_frame)
  398. {
  399. se_output->request(seInfo->effect_id, relVolume );
  400. }
  401. }
  402. // --------- end of function SERes::far_sound ----------//
  403. // --------- begin of function SERes::mark_select_object_time ----------//
  404. int SERes::mark_select_object_time() // return false if this sound should be skipped due to too frequent
  405. {
  406. unsigned long t = m.get_time();
  407. if( t - last_select_time >= select_sound_length )
  408. {
  409. last_select_time = t;
  410. return 1;
  411. }
  412. return 0;
  413. }
  414. // --------- end of function SERes::mark_select_object_time ----------//
  415. // --------- begin of function SERes::mark_select_object_time ----------//
  416. int SERes::mark_command_time() // return false if this sound should be skipped due to too frequent
  417. {
  418. unsigned long t = m.get_time();
  419. // if( t - last_command_time >= select_sound_length )
  420. // {
  421. // last_command_time = t;
  422. // return 1;
  423. // }
  424. if( t - last_select_time >= select_sound_length )
  425. {
  426. last_select_time = t;
  427. return 1;
  428. }
  429. return 0;
  430. }
  431. // --------- end of function SERes::mark_select_object_time ----------//
  432. //-------------- Begin Function SERes::random ---------//
  433. unsigned SERes::random(unsigned bound)
  434. {
  435. #define MULTIPLIER 0x015a4e35L
  436. #define INCREMENT 1
  437. seed = MULTIPLIER * seed + INCREMENT;
  438. return seed % bound;
  439. }
  440. //-------------- End Function SERes::random ---------//