PageRenderTime 51ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/Game_DarkForces/ScriptFiles/CoreLogics.as

#
ActionScript | 4420 lines | 3416 code | 507 blank | 497 comment | 715 complexity | 2eaa4f9a0c0ef0ccce0408177b9cf406 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. *******obj variables********
  3. obj_Speed
  4. obj_dY
  5. obj_HP
  6. obj_Shields
  7. obj_Radius
  8. obj_Frame
  9. obj_Delay
  10. obj_FrameDelay
  11. obj_Alive
  12. obj_Action
  13. obj_Alerted
  14. obj_Yaw
  15. obj_dir_x
  16. obj_dir_y
  17. obj_dir_z
  18. obj_loc_x
  19. obj_loc_y
  20. obj_loc_z
  21. obj_uMsg
  22. *******player variables********
  23. *******obj Functions********
  24. Obj_SetMoveDir(float x, float y, float z)
  25. Obj_SetFlag(flag)
  26. Obj_ClearFlag(flag)
  27. Obj_UpdateLoc()
  28. Obj_SetProjectileData(string &type, string &projGraphic, string &projImpactGraph, string &fireSnd, string &hitSnd, int nDamage, float fSplashRng)
  29. *******sprite/wax functions*****
  30. Sprite_GetFrameCnt(action, view)
  31. *******logic Functions**********
  32. Logic_AddMsgMask(mask)
  33. *******map Functions**********
  34. Map_AddObject(type, file, logic, rot)
  35. float Map_GetFloorHeight()
  36. float Map_GetCeilingHeight()
  37. */
  38. const float dt = 1.0f/60.0f;
  39. //for now I have to duplicate engine enums...
  40. /*******Screen Flash Colors****/
  41. const int PLAYER_FLASH_RED =0;
  42. const int PLAYER_FLASH_GREEN=1;
  43. const int PLAYER_FLASH_BLUE =2;
  44. /*******STD. VALUES*********/
  45. const int FALSE = 0;
  46. const int TRUE = 1;
  47. const float PI = 3.141592653589793238f;
  48. const float TWO_PI = 6.283185307179586477f;
  49. /*******MESSAGE ENUMS*******/
  50. const int MSG_NRML_DAMAGE = 1; //called when an object recieves "normal" damage (such as blaster fire).
  51. const int MSG_MELEE_DAMAGE = 2; //called when an object recieves "melee" damage (such as Kyle's fist).
  52. const int MSG_ALERT = 4; //called when an object is "alerted"
  53. const int MSG_ANIM_LOOP = 8; //called when an animation loops, this can be used for transitions.
  54. const int MSG_PICKUP = 16; //called when the player collides with a pickup.
  55. const int MSG_MASTER_ON = 32; //sent to logics of objects in a sector when it recieves the master on message (INF).
  56. const int MSG_OBJ_DEAD = 64; //the logic was setup to handle an object's death.
  57. const int MSG_PROXIMITY = 128; //sent to a logic, when an object is nearby (use with player collision flag to make it only the player).
  58. /*******OBJECT FLAGS*******/
  59. const int OFLAGS_COLLIDE_PLAYER = 1;
  60. const int OFLAGS_COLLIDE_PROJECTILE = 2;
  61. const int OFLAGS_COLLIDE_OBJECTS = 8;
  62. const int OFLAGS_COLLIDE_PICKUP = 16;
  63. const int OFLAGS_COLLIDE_PROXIMITY = 32;
  64. const int OFLAGS_ENEMY = 64;
  65. const int OFLAGS_INVISIBLE = 1024;
  66. /*******AMMO TYPES********/
  67. const int AMMO_ENERGY = 0;
  68. const int AMMO_DETONATOR = 1;
  69. const int AMMO_POWER = 2;
  70. const int AMMO_MINE = 3;
  71. const int AMMO_MORTOR = 4;
  72. const int AMMO_PLASMA = 5;
  73. const int AMMO_MISSLE = 6;
  74. /*******Animation Actions*********/
  75. const int Anim_Moving = 0;
  76. const int Anim_Attacking = 1;
  77. const int Anim_Dying_Melee = 2;
  78. const int Anim_Dying_Nrml = 3;
  79. const int Anim_Dead = 4;
  80. const int Anim_Idle = 5;
  81. const int Anim_PAttack_FT = 6; //Primary attack follow through
  82. const int Anim_Sec_Attack = 7; //Secondary attack
  83. const int Anim_SAttack_FT = 8; //Secondary attack follow through.
  84. const int Anim_Injured = 12;
  85. /***********AI Routines*************/
  86. const int AI_State = 0;
  87. const int AI_Prev_State = 1;
  88. const int AI_Sec_State = 1;
  89. const int AI_Reaction = 2;
  90. const int AI_Dir = 3;
  91. const int AI_Sound = 4;
  92. const int AI_ProjGraph = 5;
  93. const int AI_ShootFT = 6;
  94. const int AI_Flags = 7;
  95. const int AI_Attack = 8;
  96. const int AI_Melee_Attack = 9;
  97. const int AI_Min_Reaction = 10;
  98. const int AI_Walk_Delay = 11;
  99. const int AI_Shoot_Cone = 12;
  100. const int AI_Shoot_Height = 13;
  101. const int AI_Shoot_Delay = 14;
  102. const int AI_MaxAttackRange = 15;
  103. //list of general AI states.
  104. const int AI_State_Look = 0; //look for the player but don't move - default state for standard enemies.
  105. const int AI_State_Chase = 1; //chase the player.
  106. const int AI_State_Wander = 2; //wander around - default state for generators.
  107. const int AI_State_Attack_Melee = 3; //melee attack.
  108. const int AI_State_Attack_Range = 4; //range attack (blaster, thermal detonator, etc.)
  109. const int AI_State_Wander_UG = 5; //wander state for units that travel underground - ie the sewer bugs...
  110. const int AI_State_Remote = 6; //special code for the Remote.
  111. const int AI_State_Transition = 256;
  112. //list of general AI flags.
  113. const int AI_Flags_None = 0;
  114. const int AI_Flags_Allow_Double_Shoot = 1;
  115. const int AI_Flags_Has_Melee = 2;
  116. const int AI_Flags_Floating = 4;
  117. const int AI_Flags_NoAlert = 8;
  118. const int AI_Flags_NoRangeAttck = 16;
  119. const int AI_Flags_Underground = 32;
  120. const int AI_Flags_SingleAttckOnly = 64;
  121. const int AI_Flags_FloatOnWater = 128;
  122. const int AI_Flags_Melee_Random = 256; //Don't always attack when in range, random chance.
  123. const int AI_Flags_ShootExp = 512;
  124. const int AI_Flags_MeleeWhileInjured = 1024;
  125. const int AI_Flags_JustFiredTwice = 2048;
  126. //misc. values.
  127. const float MeleeRange = 8.0f;
  128. const float MinRngAttackDist = 3.0f;
  129. //Setup for AI.
  130. void L_AI_SetupLogic()
  131. {
  132. Logic_AddMsgMask(MSG_NRML_DAMAGE);
  133. Logic_AddMsgMask(MSG_MELEE_DAMAGE);
  134. Logic_AddMsgMask(MSG_ALERT);
  135. }
  136. void L_AI_SetupObj(int HP, int inital_AI_state, int fireSound, int projGraph, int aiRngAttck, int aiMeleeAttck, bool bShootFT, int aiFlags)
  137. {
  138. Obj_SetMoveDir( obj_dir_x, obj_dir_y, 0.0f );
  139. obj_Speed = 0.1f;
  140. obj_dY = 0.015f;
  141. obj_HP = HP;
  142. obj_Radius = 2.0f;
  143. obj_Height = 7.8f;
  144. Obj_SetFlag(OFLAGS_COLLIDE_PLAYER);
  145. Obj_SetFlag(OFLAGS_COLLIDE_PROJECTILE);
  146. Obj_SetFlag(OFLAGS_COLLIDE_OBJECTS);
  147. Obj_SetFlag(OFLAGS_ENEMY);
  148. Obj_EnableAnim(1);
  149. //put into the "idle" action...
  150. obj_Action = Anim_Idle;
  151. obj_Frame = 0;
  152. obj_Delay = 15;
  153. obj_FrameDelay = 15;
  154. Obj_SetLocalVar(AI_State, inital_AI_state);
  155. Obj_SetLocalVar(AI_Prev_State, inital_AI_state);
  156. Obj_SetLocalVar(AI_Reaction, 5);
  157. Obj_SetLocalVar(AI_Sound, fireSound);
  158. Obj_SetLocalVar(AI_ProjGraph, projGraph);
  159. Obj_SetLocalVar(AI_ShootFT, bShootFT?1:0);
  160. Obj_SetLocalVar(AI_Flags, aiFlags);
  161. Obj_SetLocalVar(AI_Attack, aiRngAttck);
  162. Obj_SetLocalVar(AI_Melee_Attack, aiMeleeAttck);
  163. Obj_SetLocalVar(AI_Min_Reaction, Sprite_GetFrameCnt(Anim_Moving, 0)*5);//*15);
  164. Obj_SetLocalVar(AI_Walk_Delay, 15);
  165. Obj_SetLocalVar(AI_Shoot_Cone, 0.05f);
  166. Obj_SetLocalVar(AI_Shoot_Height, 0.0f);
  167. Obj_SetLocalVar(AI_Shoot_Delay, 15);
  168. Obj_SetLocalVar(AI_MaxAttackRange, 512);
  169. }
  170. int ChooseMoveDir(int nPlayerRel)
  171. {
  172. int f, l, r, b, dir;
  173. float px, py, pz, dx, dy;
  174. if ( nPlayerRel > 0 )
  175. {
  176. Player_GetLoc(px, py, pz);
  177. dx = px-obj_loc_x;
  178. dy = py-obj_loc_y;
  179. dir = Math_GetClosestDir(dx, dy);
  180. }
  181. else
  182. {
  183. //pick a direction at random...
  184. int r = Math_Rand();
  185. //8 directions, pick one...
  186. dir = r % 8;
  187. }
  188. Math_GetDir(dir, dx, dy);
  189. f = dir;
  190. //is this direction blocked?
  191. float p1_x = dx*obj_Speed + obj_loc_x;
  192. float p1_y = dy*obj_Speed + obj_loc_y;
  193. if ( Map_IsPathBlocked(p1_x, p1_y, obj_Radius, TRUE) )
  194. {
  195. //right or left?
  196. int dirTry;
  197. int r = Math_Rand();
  198. int a, b;
  199. if ( r < 50 ) { a = -1; b = +1; }
  200. else { a = +1; b = -1; }
  201. l = a; r = b;
  202. dirTry = dir+a;
  203. if ( dirTry > 7 ) dirTry -= 8;
  204. if ( dirTry < 0 ) dirTry += 8;
  205. Math_GetDir(dirTry, dx, dy);
  206. p1_x = dx*obj_Speed + obj_loc_x;
  207. p1_y = dy*obj_Speed + obj_loc_y;
  208. if ( Map_IsPathBlocked(p1_x, p1_y, obj_Radius, TRUE) )
  209. {
  210. dirTry = dir+b;
  211. if ( dirTry > 7 ) dirTry -= 8;
  212. if ( dirTry < 0 ) dirTry += 8;
  213. Math_GetDir(dirTry, dx, dy);
  214. p1_x = dx*obj_Speed + obj_loc_x;
  215. p1_y = dy*obj_Speed + obj_loc_y;
  216. if ( Map_IsPathBlocked(p1_x, p1_y, obj_Radius, TRUE) )
  217. {
  218. //left and right is blocked, try going backwards...
  219. r = Math_Rand();
  220. if ( r < 25 ) { dirTry = dir+3; }
  221. else if (r < 75) { dirTry = dir+4; }
  222. else { dirTry = dir+5; }
  223. if ( dirTry > 7 ) dirTry -= 8;
  224. if ( dirTry < 0 ) dirTry += 8;
  225. b = dirTry;
  226. Math_GetDir(dirTry, dx, dy);
  227. p1_x = dx*obj_Speed + obj_loc_x;
  228. p1_y = dy*obj_Speed + obj_loc_y;
  229. if ( Map_IsPathBlocked(p1_x, p1_y, obj_Radius, TRUE) )
  230. {
  231. //we'll try all the other directions now...
  232. for (int i=0; i<8; i++)
  233. {
  234. if ( i == f || i == l || i == r || i == b ) { continue; }
  235. Math_GetDir(i, dx, dy);
  236. p1_x = dx*obj_Speed + obj_loc_x;
  237. p1_y = dy*obj_Speed + obj_loc_y;
  238. if ( !Map_IsPathBlocked(p1_x, p1_y, obj_Radius, TRUE) )
  239. {
  240. Obj_LookAt(p1_x, p1_y, obj_loc_z, 1.0f, 0);
  241. return i;
  242. }
  243. }
  244. //can't move...
  245. return -1;
  246. }
  247. else
  248. {
  249. Obj_LookAt(p1_x, p1_y, obj_loc_z, 1.0f, 0);
  250. return dirTry;
  251. }
  252. }
  253. else
  254. {
  255. Obj_LookAt(p1_x, p1_y, obj_loc_z, 1.0f, 0);
  256. return dirTry;
  257. }
  258. }
  259. else
  260. {
  261. Obj_LookAt(p1_x, p1_y, obj_loc_z, 1.0f, 0);
  262. return dirTry;
  263. }
  264. }
  265. Obj_LookAt(p1_x, p1_y, obj_loc_z, 1.0f, 0);
  266. return dir;
  267. }
  268. //Chase the player.
  269. void L_AI_Chase(bool bTransition)
  270. {
  271. if ( bTransition )
  272. {
  273. obj_Action = Anim_Moving;
  274. obj_Frame = 0;
  275. obj_Delay = Obj_GetLocalVar(AI_Walk_Delay);//15;
  276. obj_FrameDelay = Obj_GetLocalVar(AI_Walk_Delay);//15;
  277. Obj_SetLocalVar( AI_Reaction, Obj_GetLocalVar(AI_Min_Reaction));
  278. Obj_SetLocalVar(AI_Prev_State, Obj_GetLocalVar(AI_State));
  279. Obj_SetLocalVar(AI_State, AI_State_Chase);
  280. //pick a direction.
  281. Obj_SetLocalVar( AI_Dir, ChooseMoveDir(1) );
  282. if ( Obj_GetLocalVarI(AI_Flags)&AI_Flags_Underground > 0 )
  283. {
  284. Obj_SetFlag(OFLAGS_INVISIBLE);
  285. Obj_ClearFlag(OFLAGS_COLLIDE_PLAYER);
  286. Obj_ClearFlag(OFLAGS_COLLIDE_PROJECTILE);
  287. }
  288. }
  289. int reaction = Obj_GetLocalVar(AI_Reaction);
  290. reaction--;
  291. if ( reaction <= 0 )
  292. {
  293. if ( Obj_GetLocalVarI(AI_Flags)&AI_Flags_Underground > 0 )
  294. {
  295. Obj_ClearFlag(OFLAGS_INVISIBLE);
  296. Obj_SetFlag(OFLAGS_COLLIDE_PLAYER);
  297. Obj_SetFlag(OFLAGS_COLLIDE_PROJECTILE);
  298. }
  299. Obj_SetLocalVar(AI_Reaction, 5);
  300. //we'll either attack or pick a direction to move in.
  301. float d = Obj_GetDistFromPlayer();
  302. if ( d < MeleeRange && (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Has_Melee)>0 )
  303. {
  304. //change of attack?
  305. int r = Math_Rand();
  306. int chance = 100;
  307. if ( (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Melee_Random)>0 )
  308. {
  309. chance = 20;
  310. }
  311. //try melee attack if possible.
  312. if ( ( r < chance || chance == 100 ) && Map_HasPlayerLOS() == 1 )
  313. {
  314. Obj_SetLocalVar(AI_Prev_State, Obj_GetLocalVar(AI_State));
  315. Obj_SetLocalVar(AI_State,AI_State_Attack_Melee|AI_State_Transition);
  316. return;
  317. }
  318. else
  319. {
  320. //change direction.
  321. Obj_SetLocalVar( AI_Reaction, Obj_GetLocalVar(AI_Min_Reaction));
  322. //pick a direction.
  323. Obj_SetLocalVar( AI_Dir, ChooseMoveDir(1) );
  324. }
  325. }
  326. else
  327. {
  328. int r = Math_Rand();
  329. //the chance of shooting is proportional to the distance from the player.
  330. int t = d*0.5f;
  331. //units will always shoot atleast roughly half the time.
  332. if ( t > 60 ) t = 60;
  333. if ( r > t && Map_HasPlayerLOS() == 1 && d > MinRngAttackDist && d < Obj_GetLocalVar(AI_MaxAttackRange) && (Obj_GetLocalVarI(AI_Flags)&AI_Flags_NoRangeAttck)==0 )
  334. {
  335. Obj_SetLocalVar(AI_Prev_State, Obj_GetLocalVar(AI_State));
  336. Obj_SetLocalVar(AI_State,AI_State_Attack_Range|AI_State_Transition);
  337. return;
  338. }
  339. else
  340. {
  341. //change direction.
  342. Obj_SetLocalVar( AI_Reaction, Obj_GetLocalVar(AI_Min_Reaction));
  343. //pick a direction.
  344. Obj_SetLocalVar( AI_Dir, ChooseMoveDir(1) );
  345. if ( Obj_GetLocalVarI(AI_Flags)&AI_Flags_Underground > 0 )
  346. {
  347. Obj_SetFlag(OFLAGS_INVISIBLE);
  348. Obj_ClearFlag(OFLAGS_COLLIDE_PLAYER);
  349. Obj_ClearFlag(OFLAGS_COLLIDE_PROJECTILE);
  350. }
  351. }
  352. }
  353. }
  354. else
  355. {
  356. Obj_SetLocalVar(AI_Reaction, reaction);
  357. }
  358. //continue moving in the current direction unless it is blocked.
  359. float p1_x, p1_y;
  360. int dir = Obj_GetLocalVar(AI_Dir);
  361. if (dir == -1)
  362. {
  363. dir = ChooseMoveDir(1);
  364. if (dir > 0)
  365. {
  366. p1_x = obj_loc_x + obj_dir_x*obj_Speed;
  367. p1_y = obj_loc_y + obj_dir_y*obj_Speed;
  368. Obj_SetLocalVar( AI_Dir, dir );
  369. }
  370. else
  371. {
  372. if ( (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Floating)>0 )
  373. {
  374. //try moving down a little...
  375. obj_loc_z -= 0.02f;
  376. Obj_UpdateLoc();
  377. }
  378. }
  379. }
  380. else
  381. {
  382. p1_x = obj_loc_x + obj_dir_x*obj_Speed;
  383. p1_y = obj_loc_y + obj_dir_y*obj_Speed;
  384. if ( Map_IsPathBlocked(p1_x, p1_y, obj_Radius, TRUE) )
  385. {
  386. dir = ChooseMoveDir(1);
  387. if ( dir > 0 )
  388. {
  389. p1_x = obj_loc_x + obj_dir_x*obj_Speed;
  390. p1_y = obj_loc_y + obj_dir_y*obj_Speed;
  391. }
  392. else if ( (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Floating)>0 )
  393. {
  394. //try moving down a little...
  395. obj_loc_z -= 0.02f;
  396. Obj_UpdateLoc();
  397. }
  398. Obj_SetLocalVar( AI_Dir, dir );
  399. }
  400. }
  401. if ( dir > -1 )
  402. {
  403. //this will move toward (p1_x, p1_y) and colliding in the process.
  404. //treat drops as solid unless its a floating unit.
  405. float z = obj_loc_z;
  406. Map_CollideObj(p1_x, p1_y, obj_Radius, TRUE, (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Floating)>0 ? FALSE : TRUE, TRUE);
  407. if ( (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Floating)>0 )
  408. {
  409. obj_loc_z = z;
  410. Obj_UpdateLoc();
  411. }
  412. }
  413. else if ( (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Floating)>0 )
  414. {
  415. //try moving down a little...
  416. obj_loc_z -= 0.02f;
  417. Obj_UpdateLoc();
  418. }
  419. //move down toward the player...
  420. if ( (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Floating)>0 )
  421. {
  422. float px, py, pz;
  423. float ground_height = Map_GetFloorHeight(0, -1);
  424. float ceil_height = Map_GetCeilingHeight(-1);
  425. Player_GetLoc(px, py, pz);
  426. if ( obj_loc_z > pz+5.0f && obj_loc_z >= ground_height + 5.04f)
  427. {
  428. //try moving down a little...
  429. obj_loc_z -= 0.02f;
  430. Obj_UpdateLoc();
  431. }
  432. if ( obj_loc_z < pz+3.0f && obj_loc_z <= ceil_height-4.04f )
  433. {
  434. //try moving up a little...
  435. obj_loc_z += 0.02f;
  436. Obj_UpdateLoc();
  437. }
  438. }
  439. }
  440. //Wander around, player has not been sighted yet.
  441. void L_AI_Wander(bool bTransition)
  442. {
  443. if ( bTransition )
  444. {
  445. if ( Obj_GetLocalVarI(AI_Flags)&AI_Flags_Underground > 0 )
  446. {
  447. L_AI_Wander_UG(true);
  448. return;
  449. }
  450. obj_Action = Anim_Moving;
  451. obj_Frame = 0;
  452. obj_Delay = Obj_GetLocalVar(AI_Walk_Delay);//15;
  453. obj_FrameDelay = Obj_GetLocalVar(AI_Walk_Delay);//15;
  454. Obj_SetLocalVar( AI_Reaction, Obj_GetLocalVar(AI_Min_Reaction));
  455. Obj_SetLocalVar(AI_Prev_State, Obj_GetLocalVar(AI_State));
  456. Obj_SetLocalVar(AI_State, AI_State_Wander);
  457. //pick a direction.
  458. Obj_SetLocalVar( AI_Dir, ChooseMoveDir(0) );
  459. }
  460. int reaction = Obj_GetLocalVar(AI_Reaction);
  461. reaction--;
  462. if ( reaction <= 0 )
  463. {
  464. Obj_SetLocalVar( AI_Reaction, Obj_GetLocalVar(AI_Min_Reaction));
  465. //pick a direction.
  466. Obj_SetLocalVar( AI_Dir, ChooseMoveDir(0) );
  467. }
  468. else
  469. {
  470. Obj_SetLocalVar(AI_Reaction, reaction);
  471. }
  472. //continue moving in the current direction unless it is blocked.
  473. float p1_x, p1_y;
  474. int dir = Obj_GetLocalVar(AI_Dir);
  475. if (dir == -1)
  476. {
  477. dir = ChooseMoveDir(0);
  478. if (dir > 0)
  479. {
  480. p1_x = obj_loc_x + obj_dir_x*obj_Speed;
  481. p1_y = obj_loc_y + obj_dir_y*obj_Speed;
  482. Obj_SetLocalVar( AI_Dir, dir );
  483. }
  484. else
  485. {
  486. if ( (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Floating)>0 )
  487. {
  488. //try moving down a little...
  489. obj_loc_z -= 0.02f;
  490. Obj_UpdateLoc();
  491. }
  492. }
  493. }
  494. else
  495. {
  496. p1_x = obj_loc_x + obj_dir_x*obj_Speed;
  497. p1_y = obj_loc_y + obj_dir_y*obj_Speed;
  498. if ( Map_IsPathBlocked(p1_x, p1_y, obj_Radius, TRUE) )
  499. {
  500. dir = ChooseMoveDir(0);
  501. if ( dir > 0 )
  502. {
  503. p1_x = obj_loc_x + obj_dir_x*obj_Speed;
  504. p1_y = obj_loc_y + obj_dir_y*obj_Speed;
  505. }
  506. else if ( (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Floating)>0 )
  507. {
  508. //try moving down a little...
  509. obj_loc_z -= 0.02f;
  510. Obj_UpdateLoc();
  511. }
  512. Obj_SetLocalVar( AI_Dir, dir );
  513. }
  514. }
  515. if ( dir > -1 )
  516. {
  517. //this will move toward (p1_x, p1_y) and colliding in the process.
  518. //treat drops as solid unless its a floating unit.
  519. float z = obj_loc_z;
  520. Map_CollideObj(p1_x, p1_y, obj_Radius, TRUE, (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Floating)>0 ? FALSE : TRUE, TRUE);
  521. if ( (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Floating)>0 )
  522. {
  523. obj_loc_z = z;
  524. Obj_UpdateLoc();
  525. }
  526. }
  527. else if ( (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Floating)>0 )
  528. {
  529. //try moving down a little...
  530. obj_loc_z -= 0.02f;
  531. Obj_UpdateLoc();
  532. }
  533. }
  534. //Attempt to attack from range.
  535. bool L_AI_Attack(bool bMelee, bool bTransition, int meleeSnd, int meleeDmg)
  536. {
  537. //let the game know this enemy is attacking, so iMuse can be used appropriately.
  538. Obj_EnemyAttacking();
  539. if ( bTransition )
  540. {
  541. Obj_SetLocalVar(AI_State, bMelee?AI_State_Attack_Melee:AI_State_Attack_Range);
  542. }
  543. if ( bMelee )
  544. {
  545. //melee attack now...
  546. if ( bTransition )
  547. {
  548. obj_Action = Obj_GetLocalVarI(AI_Melee_Attack);
  549. obj_Frame = 0;
  550. obj_Delay = Obj_GetLocalVarI(AI_Shoot_Delay);
  551. obj_FrameDelay = Obj_GetLocalVarI(AI_Shoot_Delay);
  552. //play sound.
  553. if ( meleeSnd == 0 ) Sound_Play3D("INTSTUN.VOC", 1.0f);
  554. else if ( meleeSnd == 1 ) Sound_Play3D("CREATUR2.VOC", 1.0f);
  555. else if ( meleeSnd == 2 ) Sound_Play3D("AXE-1.VOC", 1.0f);
  556. else if ( meleeSnd == 3 ) Sound_Play3D("KELL-5.VOC", 1.0f);
  557. else if ( meleeSnd == 4 ) Sound_Play3D("SWORD-1.VOC", 1.0f);
  558. }
  559. else
  560. {
  561. if ( obj_Action == Obj_GetLocalVarI(AI_Melee_Attack) && obj_Frame == 0 && obj_Delay == Obj_GetLocalVarI(AI_Shoot_Delay) )
  562. {
  563. //melee...
  564. float d = Obj_GetDistFromPlayer();
  565. if ( d < MeleeRange )
  566. {
  567. Player_DmgHealth(meleeDmg);
  568. }
  569. //am I still in melee range? if so continue to attack...
  570. if ( d < MeleeRange && (Obj_GetLocalVarI(AI_Flags)&AI_Flags_SingleAttckOnly)==0 )
  571. {
  572. //play sound.
  573. if ( meleeSnd == 0 ) Sound_Play3D("INTSTUN.VOC", 1.0f);
  574. else if ( meleeSnd == 1 ) Sound_Play3D("CREATUR2.VOC", 1.0f);
  575. else if ( meleeSnd == 2 ) Sound_Play3D("AXE-1.VOC", 1.0f);
  576. else if ( meleeSnd == 3 ) Sound_Play3D("KELL-5.VOC", 1.0f);
  577. else if ( meleeSnd == 4 ) Sound_Play3D("SWORD-1.VOC", 1.0f);
  578. return true;
  579. }
  580. else
  581. {
  582. L_AI_Chase(true);
  583. return false;
  584. }
  585. }
  586. }
  587. }
  588. else
  589. {
  590. if ( bTransition )
  591. {
  592. obj_Action = Obj_GetLocalVarI(AI_Attack);
  593. obj_Frame = 0;
  594. obj_Delay = Obj_GetLocalVarI(AI_Shoot_Delay);
  595. obj_FrameDelay = Obj_GetLocalVarI(AI_Shoot_Delay);
  596. }
  597. else
  598. {
  599. if ( obj_Action == Obj_GetLocalVarI(AI_Attack) && obj_Frame == 0 && obj_Delay == Obj_GetLocalVarI(AI_Shoot_Delay) )
  600. {
  601. //shoot...
  602. if ( (Obj_GetLocalVarI(AI_Flags)&AI_Flags_ShootExp) != 0 )
  603. {
  604. //Add an explosion at the player's position...
  605. if ( Map_HasPlayerLOS() == 1 )
  606. {
  607. float px, py, pz;
  608. Player_GetLoc(px, py, pz);
  609. //the direction from the object to the player.
  610. float dx = px - obj_loc_x;
  611. float dy = py - obj_loc_y;
  612. float nx, ny;
  613. Math_Normalize(dx, dy, nx, ny);
  614. //bias the explosion away from the player by 0.5 DFU, so that it is actually visible.
  615. px = px - nx*0.1f;
  616. py = py - ny*0.1f;
  617. //x, y, z, radius, damage, delay, scale, graphic (sprite), sound
  618. Map_AddExplosion(px, py, pz, 10.0f, 30.0f, 0.0f, 1.0f, "CONCEXP.WAX", "CONCUSS5.VOC", false, Player_GetSector());
  619. }
  620. }
  621. else if ( (Obj_GetLocalVarI(AI_Flags)&AI_Flags_NoRangeAttck)==0 )
  622. {
  623. int shoot = Obj_ShootPlayer( 0, Obj_GetLocalVar(AI_Shoot_Cone), Obj_GetLocalVar(AI_Sound), Obj_GetLocalVarI(AI_Shoot_Height) ); //use blaster bolts...
  624. if ( shoot == 0 )
  625. {
  626. L_AI_Chase(true);
  627. return false;
  628. }
  629. }
  630. if ( Obj_GetLocalVar(AI_ShootFT) > 0 )
  631. {
  632. obj_Frame = 0;
  633. obj_Delay = 15;
  634. obj_FrameDelay = 15;
  635. obj_Action = Anim_PAttack_FT;
  636. }
  637. else if ( obj_Speed > 0.3f && Map_HasPlayerLOS() == 1 )
  638. {
  639. obj_Action = Obj_GetLocalVarI(AI_Attack);
  640. obj_Frame = 0;
  641. obj_Delay = Obj_GetLocalVarI(AI_Shoot_Delay);
  642. obj_FrameDelay = Obj_GetLocalVarI(AI_Shoot_Delay);
  643. }
  644. else
  645. {
  646. L_AI_Chase(true);
  647. return false;
  648. }
  649. }
  650. else if ( obj_Action == Anim_PAttack_FT )
  651. {
  652. if ( obj_Frame == 0 && obj_Delay == 15 )
  653. {
  654. //we're done, now go back to chasing...
  655. int r = Math_Rand();
  656. //if we've already fired twice in a row, we can't do it again.
  657. if ( (Obj_GetLocalVarI(AI_Flags)&AI_Flags_JustFiredTwice)>0 )
  658. {
  659. //Make sure to clear the flag so we can fire twice in a row again in the future.
  660. Obj_SetLocalVar( AI_Flags, Math_ClearBit(Obj_GetLocalVar(AI_Flags), AI_Flags_JustFiredTwice) );
  661. r = 100;
  662. }
  663. if ( (r<33) && (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Allow_Double_Shoot)>0 )
  664. {
  665. obj_Action = Obj_GetLocalVarI(AI_Attack);
  666. obj_Frame = 0;
  667. obj_Delay = Obj_GetLocalVarI(AI_Shoot_Delay);
  668. obj_FrameDelay = Obj_GetLocalVarI(AI_Shoot_Delay);
  669. //Note that we've fired twice in a row so that we don't fire again atleast until another chase sequence.
  670. Obj_SetLocalVar( AI_Flags, Obj_GetLocalVarI(AI_Flags)|AI_Flags_JustFiredTwice );
  671. }
  672. else
  673. {
  674. //Reposition ourselves... unless we're turrents.:)
  675. L_AI_Chase(true);
  676. return false;
  677. }
  678. }
  679. }
  680. }
  681. }
  682. return true;
  683. }
  684. void L_AI_Wander_UG(bool bTransition)
  685. {
  686. //States: Looking around, moving under ground, attacking.
  687. if ( bTransition )
  688. {
  689. obj_Action = 12;
  690. obj_Frame = 0;
  691. obj_Delay = 10;
  692. obj_FrameDelay = 10;
  693. Obj_SetLocalVar(AI_Reaction, Sprite_GetFrameCnt(12, 0)*obj_FrameDelay);
  694. Obj_SetLocalVar(AI_Sec_State, 0);
  695. Obj_SetLocalVar(AI_State, AI_State_Wander_UG);
  696. //pick a direction.
  697. Obj_SetLocalVar( AI_Dir, ChooseMoveDir(0) );
  698. }
  699. int reaction = Obj_GetLocalVar(AI_Reaction);
  700. reaction--;
  701. if ( reaction <= 0 )
  702. {
  703. //2 possible states: come up for "air" and move
  704. if ( Obj_GetLocalVarI(AI_Sec_State) < 2 && (obj_Action != Anim_Attacking) )
  705. {
  706. //go ahead and move now...
  707. obj_Action = Anim_Idle;
  708. Obj_SetLocalVar(AI_Sec_State, 2);
  709. int r = Math_Rand();
  710. Obj_SetLocalVar(AI_Reaction, 60+r*2);
  711. Obj_SetFlag(OFLAGS_INVISIBLE);
  712. Obj_ClearFlag(OFLAGS_COLLIDE_PLAYER);
  713. Obj_ClearFlag(OFLAGS_COLLIDE_PROJECTILE);
  714. obj_Frame = 0;
  715. obj_Delay = 15;
  716. obj_FrameDelay = 15;
  717. int dir = ChooseMoveDir(0);
  718. Obj_SetLocalVar( AI_Dir, dir );
  719. }
  720. else
  721. {
  722. if ( obj_Action == Anim_Attacking )
  723. {
  724. //let the game know this enemy is attacking, so iMuse can be used appropriately.
  725. Obj_EnemyAttacking();
  726. obj_Action = Anim_PAttack_FT;
  727. obj_FrameDelay = 10;
  728. //go ahead and do the attack and sound now...
  729. float d = Obj_GetDistFromPlayer();
  730. float px, py, pz;
  731. Player_GetLoc(px, py, pz);
  732. if ( d < MeleeRange && Math_Abs(obj_loc_z-pz)<7.0f )
  733. {
  734. Player_DmgHealth(20);
  735. }
  736. Sound_Play3D("CREATUR2.VOC", 1.0f);
  737. }
  738. else
  739. {
  740. //come up for "air" and look around or attack.
  741. //are we close enough to try a melee attack?
  742. float d = Obj_GetDistFromPlayer();
  743. if ( d < MeleeRange && Map_IsPlayerInSector(obj_Radius)==1 )
  744. {
  745. obj_Action = Anim_Attacking;
  746. Obj_SetLocalVar(AI_Sec_State, 1);
  747. obj_FrameDelay = 10;
  748. }
  749. else
  750. {
  751. obj_Action = 12;
  752. Obj_SetLocalVar(AI_Sec_State, 0);
  753. obj_FrameDelay = 10;
  754. }
  755. }
  756. obj_Frame = 0;
  757. obj_Delay = obj_FrameDelay;
  758. Obj_SetLocalVar(AI_Reaction, Sprite_GetFrameCnt(obj_Action, 0)*obj_FrameDelay);
  759. Obj_ClearFlag(OFLAGS_INVISIBLE);
  760. Obj_SetFlag(OFLAGS_COLLIDE_PLAYER);
  761. Obj_SetFlag(OFLAGS_COLLIDE_PROJECTILE);
  762. }
  763. }
  764. else
  765. {
  766. if ( Obj_GetLocalVarI(AI_Sec_State) == 2 )
  767. {
  768. int dir = Obj_GetLocalVarI( AI_Dir );
  769. if ( dir > -1 )
  770. {
  771. float dx, dy;
  772. Math_GetDir(dir, dx, dy);
  773. float p1_x = obj_loc_x + dx*obj_Speed;
  774. float p1_y = obj_loc_y + dy*obj_Speed;
  775. //this will move toward (p1_x, p1_y) and colliding in the process.
  776. //treat drops as solid unless its a floating unit.
  777. float z = obj_loc_z;
  778. Map_CollideObj(p1_x, p1_y, obj_Radius, TRUE, TRUE, FALSE);
  779. obj_loc_z = z;
  780. Obj_UpdateLoc();
  781. }
  782. if ( reaction < 55 )
  783. {
  784. //if the player is close enough and its moved far enough, then come up to attack...
  785. float d = Obj_GetDistFromPlayer();
  786. float px, py, pz;
  787. Player_GetLoc(px, py, pz);
  788. if ( d < MeleeRange && Math_Abs(obj_loc_z-pz)<7.0f )
  789. {
  790. if ( Map_IsPlayerInSector(obj_Radius)==1 )
  791. {
  792. //let the game know this enemy is attacking, so iMuse can be used appropriately.
  793. Obj_EnemyAttacking();
  794. obj_Action = Anim_Attacking;
  795. Obj_SetLocalVar(AI_Sec_State, 1);
  796. obj_FrameDelay = 10;
  797. obj_Frame = 0;
  798. obj_Delay = obj_FrameDelay;
  799. Obj_SetLocalVar(AI_Reaction, Sprite_GetFrameCnt(obj_Action, 0)*obj_FrameDelay);
  800. Obj_ClearFlag(OFLAGS_INVISIBLE);
  801. Obj_SetFlag(OFLAGS_COLLIDE_PLAYER);
  802. Obj_SetFlag(OFLAGS_COLLIDE_PROJECTILE);
  803. }
  804. }
  805. }
  806. }
  807. else if ( Obj_GetLocalVarI(AI_Sec_State) == 0 )
  808. {
  809. float d = Obj_GetDistFromPlayer();
  810. if ( d < MeleeRange )
  811. {
  812. if ( Map_IsPlayerInSector(obj_Radius)==1 )//Map_HasPlayerLOS() == 1 )
  813. {
  814. obj_Action = Anim_Attacking;
  815. Obj_SetLocalVar(AI_Sec_State, 1);
  816. obj_FrameDelay = 10;
  817. obj_Frame = 0;
  818. obj_Delay = obj_FrameDelay;
  819. reaction = Sprite_GetFrameCnt(obj_Action, 0)*obj_FrameDelay;
  820. }
  821. }
  822. }
  823. Obj_SetLocalVar(AI_Reaction, reaction);
  824. }
  825. }
  826. void L_AI_Remote(bool bTransition)
  827. {
  828. if ( obj_Action == Anim_Dead ) { return; }
  829. //States: Looking around, moving under ground, attacking.
  830. if ( bTransition )
  831. {
  832. obj_Action = Anim_Moving;
  833. obj_Frame = 0;
  834. obj_Delay = 10;
  835. obj_FrameDelay = 10;
  836. Obj_SetLocalVar(AI_Reaction, 60);
  837. Obj_SetLocalVar(AI_Sec_State, 0);
  838. Obj_SetLocalVar(AI_State, AI_State_Remote);
  839. //pick a direction.
  840. Obj_SetLocalVar( AI_Dir, ChooseMoveDir(1) );
  841. Obj_ClearFlag(OFLAGS_INVISIBLE);
  842. Obj_SetFlag(OFLAGS_COLLIDE_PLAYER);
  843. Obj_SetFlag(OFLAGS_COLLIDE_PROJECTILE);
  844. }
  845. int reaction = Obj_GetLocalVar(AI_Reaction);
  846. reaction--;
  847. if ( reaction <= 0 )
  848. {
  849. //if player is close enough... shoot and move or just move...
  850. float d = Obj_GetDistFromPlayer();
  851. if ( d < 120 )
  852. {
  853. if ( Map_HasPlayerLOS() == 1 )
  854. {
  855. reaction = 60;
  856. }
  857. else
  858. {
  859. reaction = 240;
  860. }
  861. }
  862. }
  863. else
  864. {
  865. Obj_SetLocalVar(AI_Reaction, reaction);
  866. }
  867. //continue moving in the current direction unless it is blocked.
  868. float p1_x, p1_y;
  869. int dir = Obj_GetLocalVar(AI_Dir);
  870. if (dir == -1)
  871. {
  872. dir = ChooseMoveDir(1);
  873. if (dir > 0)
  874. {
  875. p1_x = obj_loc_x + obj_dir_x*obj_Speed;
  876. p1_y = obj_loc_y + obj_dir_y*obj_Speed;
  877. Obj_SetLocalVar( AI_Dir, dir );
  878. }
  879. }
  880. else
  881. {
  882. p1_x = obj_loc_x + obj_dir_x*obj_Speed;
  883. p1_y = obj_loc_y + obj_dir_y*obj_Speed;
  884. if ( Map_IsPathBlocked(p1_x, p1_y, obj_Radius, TRUE) )
  885. {
  886. dir = ChooseMoveDir(1);
  887. if ( dir > 0 )
  888. {
  889. p1_x = obj_loc_x + obj_dir_x*obj_Speed;
  890. p1_y = obj_loc_y + obj_dir_y*obj_Speed;
  891. }
  892. else if ( (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Floating)>0 )
  893. {
  894. //try moving down a little...
  895. obj_loc_z -= 0.02f;
  896. Obj_UpdateLoc();
  897. }
  898. Obj_SetLocalVar( AI_Dir, dir );
  899. }
  900. }
  901. if ( dir > -1 )
  902. {
  903. //this will move toward (p1_x, p1_y) and colliding in the process.
  904. //treat drops as solid unless its a floating unit.
  905. float z = obj_loc_z;
  906. Map_CollideObj(p1_x, p1_y, obj_Radius, TRUE, (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Floating)>0 ? FALSE : TRUE, TRUE);
  907. obj_loc_z = z;
  908. Obj_UpdateLoc();
  909. }
  910. else
  911. {
  912. //try moving down a little...
  913. obj_loc_z -= 0.02f;
  914. Obj_UpdateLoc();
  915. }
  916. //move down toward the player...
  917. {
  918. float px, py, pz;
  919. float ground_height = Map_GetFloorHeight(0, -1);
  920. float ceil_height = Map_GetCeilingHeight(-1);
  921. Player_GetLoc(px, py, pz);
  922. if ( obj_loc_z > pz+5.0f && obj_loc_z >= ground_height + 5.04f)
  923. {
  924. //try moving down a little...
  925. obj_loc_z -= 0.02f;
  926. Obj_UpdateLoc();
  927. }
  928. if ( obj_loc_z < pz+3.0f && obj_loc_z <= ceil_height-4.04f )
  929. {
  930. //try moving up a little...
  931. obj_loc_z += 0.02f;
  932. Obj_UpdateLoc();
  933. }
  934. }
  935. }
  936. float ceil_dist = 5.0f;
  937. int L_AI_RunAIState(int meleeSnd, int meleeDmg)
  938. {
  939. int ret = 0;
  940. //I'm dead, there is nothing to do now. Eventually updates for this AI should just be shut off.
  941. if ( obj_Action == Anim_Dead )
  942. {
  943. float ground_height = Map_GetFloorHeight( (Obj_GetLocalVarI(AI_Flags)&AI_Flags_FloatOnWater)>0 ? 1 : 0, -1 );
  944. //force gravity if this isn't a flying/floating unit.
  945. bool bUpdate = false;
  946. if ( obj_loc_z > ground_height )
  947. {
  948. obj_loc_z -= 0.4f;
  949. bUpdate = true;
  950. }
  951. if ( obj_loc_z < ground_height )
  952. {
  953. obj_loc_z = ground_height;
  954. bUpdate = true;
  955. }
  956. if (bUpdate) Obj_UpdateLoc();
  957. return 0;
  958. }
  959. bool bTrans = Math_IsBitSet( Obj_GetLocalVar(AI_State), AI_State_Transition );
  960. if ( bTrans )
  961. {
  962. Obj_SetLocalVar( AI_State, Math_ClearBit(Obj_GetLocalVar(AI_State), AI_State_Transition) );
  963. }
  964. int state = Obj_GetLocalVarI(AI_State);
  965. if ( obj_Action != Anim_Dying_Melee && obj_Action != Anim_Dying_Nrml && (obj_Action != Anim_Injured || state==AI_State_Wander_UG || state==AI_State_Remote) )
  966. {
  967. switch (state)
  968. {
  969. case AI_State_Look:
  970. obj_Action = Anim_Idle;
  971. break;
  972. case AI_State_Chase:
  973. L_AI_Chase(bTrans);
  974. break;
  975. case AI_State_Wander:
  976. L_AI_Wander(bTrans);
  977. break;
  978. case AI_State_Attack_Melee:
  979. L_AI_Attack(true, bTrans, meleeSnd, meleeDmg);
  980. break;
  981. case AI_State_Attack_Range:
  982. L_AI_Attack(false, bTrans, -1, 0);
  983. break;
  984. case AI_State_Wander_UG:
  985. L_AI_Wander_UG(bTrans);
  986. break;
  987. case AI_State_Remote:
  988. L_AI_Remote(bTrans);
  989. break;
  990. }
  991. }
  992. else if ( obj_Action == Anim_Dying_Melee && obj_Frame >= Sprite_GetFrameCnt(Anim_Dying_Melee, 0)-1 && obj_Delay < 1 )
  993. {
  994. obj_Action = Anim_Dead;
  995. ret = 1;
  996. }
  997. else if ( obj_Action == Anim_Dying_Nrml && obj_Frame >= Sprite_GetFrameCnt(Anim_Dying_Nrml, 0)-1 && obj_Delay < 1 )
  998. {
  999. obj_Action = Anim_Dead;
  1000. ret = 1;
  1001. }
  1002. else if ( state != AI_State_Wander_UG && state != AI_State_Remote && obj_Action == Anim_Injured && obj_Frame >= Sprite_GetFrameCnt(Anim_Injured, 0)-1 && obj_Delay < 1 )
  1003. {
  1004. if ( obj_Alive == 0 ) { obj_Action = Anim_Dead; ret = 1; }
  1005. else
  1006. {
  1007. float d = Obj_GetDistFromPlayer();
  1008. if ( d < MeleeRange && (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Has_Melee)>0 )
  1009. {
  1010. //try melee attack if possible.
  1011. L_AI_Attack(true, true, meleeSnd, meleeDmg);
  1012. }
  1013. else if ( (Obj_GetLocalVarI(AI_Flags)&AI_Flags_NoRangeAttck)==0 )
  1014. {
  1015. L_AI_Attack(false, true, -1, 0);
  1016. }
  1017. else
  1018. {
  1019. L_AI_Chase(true);
  1020. }
  1021. }
  1022. }
  1023. //fall to the ground if this is a ground based unit.
  1024. float ground_height = Map_GetFloorHeight( ((Obj_GetLocalVarI(AI_Flags)&AI_Flags_Floating)>0 || (Obj_GetLocalVarI(AI_Flags)&AI_Flags_FloatOnWater)>0) ? 1 : 0, -1 );
  1025. if ( obj_Action != Anim_Dying_Nrml && obj_Action != Anim_Dying_Melee && obj_Action != Anim_Dead && (Obj_GetLocalVarI(AI_Flags)&AI_Flags_Floating)>0 )
  1026. {
  1027. float ceil_height = Map_GetCeilingHeight(-1);
  1028. if ( obj_loc_z < ground_height + 5.0f )
  1029. {
  1030. obj_loc_z += 0.4f;
  1031. }
  1032. if ( obj_loc_z > ceil_height-ceil_dist )
  1033. {
  1034. obj_loc_z = ceil_height-ceil_dist;
  1035. }
  1036. }
  1037. else
  1038. {
  1039. //force gravity if this isn't a flying/floating unit.
  1040. if ( obj_loc_z > ground_height )
  1041. {
  1042. obj_loc_z -= 0.4f;
  1043. }
  1044. }
  1045. if ( obj_loc_z < ground_height )
  1046. {
  1047. obj_loc_z = ground_height;
  1048. }
  1049. Obj_UpdateLoc();
  1050. //Did I just die?
  1051. return ret;
  1052. }
  1053. bool L_AI_SendMsg(bool bSwapDeathAnim, int nDeathSnd, int nDmgSnd, int nAlertSnd)
  1054. {
  1055. bool bJustDied = false;
  1056. if ( obj_Alive == 1 )
  1057. {
  1058. switch (obj_uMsg)
  1059. {
  1060. case MSG_NRML_DAMAGE:
  1061. obj_HP -= msg_nVal;
  1062. if ( obj_HP <= 0 )
  1063. {
  1064. obj_HP = 0;
  1065. obj_Alive = 0;
  1066. obj_Frame = 0;
  1067. obj_Delay = 6;
  1068. obj_FrameDelay = 6;
  1069. obj_Action = bSwapDeathAnim ? Anim_Dying_Melee : Anim_Dying_Nrml;
  1070. Obj_ClearFlag(OFLAGS_COLLIDE_PLAYER);
  1071. Obj_ClearFlag(OFLAGS_COLLIDE_PROJECTILE);
  1072. Obj_ClearFlag(OFLAGS_COLLIDE_OBJECTS);
  1073. //-----------death---------------
  1074. if ( nDeathSnd == 0 ) Sound_Play3D("ST-DIE-1.VOC", 1.0f);
  1075. else if ( nDeathSnd == 1 ) Sound_Play3D("EX-SMALL.VOC", 1.0f);
  1076. else if ( nDeathSnd == 2 ) Sound_Play3D("PROBALM.VOC", 1.0f);
  1077. else if ( nDeathSnd == 3 ) { Sound_Play3D("REMOTE-2.VOC", 1.0f); obj_Action = Anim_Dead; }
  1078. else if ( nDeathSnd == 4 ) Sound_Play3D("CREATDIE.VOC", 1.0f);
  1079. else if ( nDeathSnd == 5 ) Sound_Play3D("REEYEE-3.VOC", 1.0f);
  1080. else if ( nDeathSnd == 6 ) Sound_Play3D("GAMOR-1.VOC", 1.0f);
  1081. else if ( nDeathSnd == 7 ) Sound_Play3D("BOSSKDIE.VOC", 1.0f);
  1082. else if ( nDeathSnd == 8 ) Sound_Play3D("KELL-7.VOC", 1.0f);
  1083. else if ( nDeathSnd == 9 ) Sound_Play3D("PHASE1C.VOC", 1.0f);
  1084. else if ( nDeathSnd == 10) Sound_Play3D("PHASE2C.VOC", 1.0f);
  1085. else if ( nDeathSnd == 11) Sound_Play3D("PHASE3C.VOC", 1.0f);
  1086. else if ( nDeathSnd == 12) Sound_Play3D("BOBA-4.VOC", 1.0f);
  1087. bJustDied = true;
  1088. Obj_JustDied();
  1089. }
  1090. else
  1091. {
  1092. int r = Math_Rand();
  1093. if ( obj_Speed > 0.3f )
  1094. {
  1095. //hack for DT's...
  1096. r = 0;
  1097. }
  1098. if ( nDmgSnd != 1 && ((Obj_GetLocalVarI(AI_Flags)&AI_Flags_MeleeWhileInjured)!=0 || r < 30) )
  1099. {
  1100. obj_Frame = 0;
  1101. obj_Delay = 15;
  1102. obj_Action = Anim_Injured;
  1103. }
  1104. //-----------damage sound---------------
  1105. if ( nDmgSnd == 0 ) Sound_Play3D("ST-HRT-1.VOC", 1.0f);
  1106. else if ( nDmgSnd == 1 ) Sound_Play3D("CREATHRT.VOC", 100.0f);
  1107. else if ( nDmgSnd == 2 ) Sound_Play3D("REEYEE-2.VOC", 1.0f);
  1108. else if ( nDmgSnd == 3 ) Sound_Play3D("GAMOR-2.VOC", 1.0f);
  1109. else if ( nDmgSnd == 4 ) Sound_Play3D("GAMOR-3.VOC", 1.0f);
  1110. else if ( nDmgSnd == 5 ) Sound_Play3D("KELL-5.VOC", 1.0f);
  1111. else if ( nDmgSnd == 6 ) Sound_Play3D("PHASE1B.VOC", 1.0f);
  1112. else if ( nDmgSnd == 7 ) Sound_Play3D("PHASE2B.VOC", 1.0f);
  1113. else if ( nDmgSnd == 8 ) Sound_Play3D("PHASE3B.VOC", 1.0f);
  1114. else if ( nDmgSnd == 9 ) Sound_Play3D("BOBA-3.VOC", 1.0f);
  1115. }
  1116. break;
  1117. case MSG_MELEE_DAMAGE:
  1118. //hack for now... double Melee damage.
  1119. if ( nDeathSnd == 8 )
  1120. obj_HP -= msg_nVal;
  1121. obj_HP -= msg_nVal;
  1122. if ( obj_HP <= 0 )
  1123. {
  1124. obj_HP = 0;
  1125. obj_Alive = 0;
  1126. obj_Frame = 0;
  1127. obj_Delay = 6;
  1128. obj_FrameDelay = 6;
  1129. obj_Action = bSwapDeathAnim ? Anim_Dying_Nrml : Anim_Dying_Melee;
  1130. Obj_ClearFlag(OFLAGS_COLLIDE_PLAYER);
  1131. Obj_ClearFlag(OFLAGS_COLLIDE_PROJECTILE);
  1132. Obj_ClearFlag(OFLAGS_COLLIDE_OBJECTS);
  1133. //-----------death---------------
  1134. if ( nDeathSnd == 0 ) Sound_Play3D("ST-DIE-1.VOC", 1.0f);
  1135. else if ( nDeathSnd == 1 ) Sound_Play3D("EX-SMALL.VOC", 1.0f);
  1136. else if ( nDeathSnd == 2 ) Sound_Play3D("PROBALM.VOC", 1.0f);
  1137. else if ( nDeathSnd == 3 ) { Sound_Play3D("REMOTE-2.VOC", 1.0f); obj_Action = Anim_Dead; }
  1138. else if ( nDeathSnd == 4 ) Sound_Play3D("CREATDIE.VOC", 1.0f);
  1139. else if ( nDeathSnd == 5 ) Sound_Play3D("REEYEE-3.VOC", 1.0f);
  1140. else if ( nDeathSnd == 6 ) Sound_Play3D("GAMOR-1.VOC", 1.0f);
  1141. else if ( nDeathSnd == 7 ) Sound_Play3D("BOSSKDIE.VOC", 1.0f);
  1142. else if ( nDeathSnd == 8 ) Sound_Play3D("KELL-7.VOC", 1.0f);
  1143. else if ( nDeathSnd == 9 ) Sound_Play3D("PHASE1C.VOC", 1.0f);
  1144. else if ( nDeathSnd == 10) Sound_Play3D("PHASE2C.VOC", 1.0f);
  1145. else if ( nDeathSnd == 11) Sound_Play3D("PHASE3C.VOC", 1.0f);
  1146. else if ( nDeathSnd == 12) Sound_Play3D("BOBA-4.VOC", 1.0f);
  1147. bJustDied = true;
  1148. Obj_JustDied();
  1149. }
  1150. else
  1151. {
  1152. int r = Math_Rand();
  1153. if ( obj_Speed > 0.3f )
  1154. {
  1155. //hack for DT's...
  1156. r = 0;
  1157. }
  1158. if ( nDmgSnd != 1 && ((Obj_GetLocalVarI(AI_Flags)&AI_Flags_MeleeWhileInjured)==0||r<30) )
  1159. {
  1160. obj_Frame = 0;
  1161. obj_Delay = 25;
  1162. obj_FrameDelay = 25;
  1163. obj_Action = Anim_Injured;
  1164. obj_loc_z += 0.5f;
  1165. Obj_UpdateLoc();
  1166. }
  1167. //-----------damage sound---------------
  1168. if ( nDmgSnd == 0 ) Sound_Play3D("ST-HRT-1.VOC", 1.0f);
  1169. else if ( nDmgSnd == 1 ) Sound_Play3D("CREATHRT.VOC", 100.0f);
  1170. else if ( nDmgSnd == 2 ) Sound_Play3D("REEYEE-2.VOC", 1.0f);
  1171. else if ( nDmgSnd == 3 ) Sound_Play3D("GAMOR-2.VOC", 1.0f);
  1172. else if ( nDmgSnd == 4 ) Sound_Play3D("GAMOR-3.VOC", 1.0f);
  1173. else if ( nDmgSnd == 5 ) Sound_Play3D("KELL-5.VOC", 1.0f);
  1174. else if ( nDmgSnd == 6 ) Sound_Play3D("PHASE1B.VOC", 1.0f);
  1175. else if ( nDmgSnd == 7 ) Sound_Play3D("PHASE2B.VOC", 1.0f);
  1176. else if ( nDmgSnd == 8 ) Sound_Play3D("PHASE3B.VOC", 1.0f);
  1177. else if ( nDmgSnd == 9 ) Sound_Play3D("BOBA-3.VOC", 1.0f);
  1178. }
  1179. break;
  1180. case MSG_ALERT:
  1181. {
  1182. if ( System_GetTimer(0) == 0 && (Obj_GetLocalVarI(AI_Flags)&AI_Flags_NoAlert)==0 )
  1183. {
  1184. if ( nAlertSnd == 0 )
  1185. {
  1186. int nAlert = System_GetGlobalVar(0);
  1187. //play alert sound...
  1188. switch (nAlert)
  1189. {
  1190. case 0:
  1191. Sound_Play3D("RANSTO01.VOC", 100.0f);
  1192. break;
  1193. case 1:
  1194. Sound_Play3D("RANSTO02.VOC", 100.0f);
  1195. break;
  1196. case 2:
  1197. Sound_Play3D("RANSTO03.VOC", 100.0f);
  1198. break;
  1199. case 3:
  1200. Sound_Play3D("RANSTO04.VOC", 100.0f);
  1201. break;
  1202. case 4:
  1203. Sound_Play3D("RANSTO05.VOC", 100.0f);
  1204. break;
  1205. case 5:
  1206. Sound_Play3D("RANSTO06.VOC", 100.0f);
  1207. break;
  1208. case 6:
  1209. Sound_Play3D("RANSTO07.VOC", 100.0f);
  1210. break;
  1211. case 7:
  1212. Sound_Play3D("RANSTO08.VOC", 100.0f);
  1213. break;
  1214. }
  1215. nAlert = (nAlert+1)%8;
  1216. System_SetGlobalVar(0, nAlert);
  1217. }
  1218. else if ( nAlertSnd == 1 )
  1219. {
  1220. Sound_Play3D("INTALERT.VOC", 100.0f);
  1221. }
  1222. else if ( nAlertSnd == 2 )
  1223. {
  1224. Sound_Play3D("PROBE-1.VOC", 100.0f);
  1225. }
  1226. else if ( nAlertSnd == 3 )
  1227. {
  1228. Sound_Play3D("REEYEE-1.VOC", 100.0f);
  1229. }
  1230. else if ( nAlertSnd == 4 )
  1231. {
  1232. Sound_Play3D("GAMOR-3.VOC", 100.0f);
  1233. }
  1234. else if ( nAlertSnd == 5 )
  1235. {
  1236. Sound_Play3D("BOSSK-1.VOC", 100.0f);
  1237. }
  1238. else if ( nAlertSnd == 6 )
  1239. {
  1240. Sound_Play3D("KELL-1.VOC", 100.0f);
  1241. }
  1242. else if ( nAlertSnd == 7 )
  1243. {
  1244. Sound_Play3D("PHASE1A.VOC", 100.0f);
  1245. }
  1246. else if ( nAlertSnd == 8 )
  1247. {
  1248. Sound_Play3D("PHASE2A.VOC", 100.0f);
  1249. }
  1250. else if ( nAlertSnd == 9 )
  1251. {
  1252. Sound_Play3D("PHASE3A.VOC", 100.0f);
  1253. }
  1254. else if ( nAlertSnd == 10 )
  1255. {
  1256. Sound_Play3D("BOBA-1.VOC", 100.0f);
  1257. }
  1258. //Reset the timer so we don't play alert sounds too often.
  1259. System_SetTimer(0, 120); //60 ticks per second, 2 second delay: 5*60 = 120
  1260. }
  1261. if ( obj_Action != Anim_Injured )
  1262. {
  1263. L_AI_Chase(true);
  1264. }
  1265. }
  1266. break;
  1267. }
  1268. }
  1269. return bJustDied;
  1270. }
  1271. /***********SPECIFIC ENEMY LOGICS***********/
  1272. //
  1273. // Logic STORM1
  1274. //
  1275. void L_STORM1_SetupLogic()
  1276. {
  1277. L_AI_SetupLogic();
  1278. }
  1279. void L_STORM1_SetupObj()
  1280. {
  1281. L_AI_SetupObj(20, AI_State_Look, 1, 0, Anim_Attacking, Anim_Sec_Attack, false, AI_Flags_None);
  1282. }
  1283. void L_STORM1_Update()
  1284. {
  1285. if ( L_AI_RunAIState(-1, 0) == 1 )
  1286. {
  1287. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "IST-GUNI.FME", "RIFLE", 0);
  1288. }
  1289. }
  1290. void L_STORM1_SendMsg()
  1291. {
  1292. L_AI_SendMsg(true, 0, 0, 0);
  1293. }
  1294. //
  1295. // Logic TROOP
  1296. //
  1297. void L_TROOP_SetupLogic()
  1298. {
  1299. L_AI_SetupLogic();
  1300. }
  1301. void L_TROOP_SetupObj()
  1302. {
  1303. L_AI_SetupObj(20, AI_State_Look, 1, 0, Anim_Attacking, Anim_Sec_Attack, false, AI_Flags_None);
  1304. }
  1305. void L_TROOP_Update()
  1306. {
  1307. if ( L_AI_RunAIState(-1, 0) == 1 )
  1308. {
  1309. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "IST-GUNI.FME", "RIFLE", 0);
  1310. }
  1311. }
  1312. void L_TROOP_SendMsg()
  1313. {
  1314. L_AI_SendMsg(true, 0, 0, 0);
  1315. }
  1316. //
  1317. // Logic I_OFFICER
  1318. //
  1319. void L_I_OFFICER_SetupLogic()
  1320. {
  1321. L_AI_SetupLogic();
  1322. }
  1323. void L_I_OFFICER_SetupObj()
  1324. {
  1325. L_AI_SetupObj(10, AI_State_Look, 0, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_None);
  1326. }
  1327. void L_I_OFFICER_Update()
  1328. {
  1329. if ( L_AI_RunAIState(-1, 0) == 1 )
  1330. {
  1331. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "IENERGY.FME", "ITEMENERGY", 0);
  1332. }
  1333. }
  1334. void L_I_OFFICER_SendMsg()
  1335. {
  1336. L_AI_SendMsg(false, 0, 0, 0);
  1337. }
  1338. //
  1339. // Logic I_OFFICERR
  1340. //
  1341. void L_I_OFFICERR_SetupLogic()
  1342. {
  1343. L_AI_SetupLogic();
  1344. }
  1345. void L_I_OFFICERR_SetupObj()
  1346. {
  1347. L_AI_SetupObj(10, AI_State_Look, 0, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_None);
  1348. }
  1349. void L_I_OFFICERR_Update()
  1350. {
  1351. if ( L_AI_RunAIState(-1, 0) == 1 )
  1352. {
  1353. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "IKEYR.FME", "RED", 0);
  1354. }
  1355. }
  1356. void L_I_OFFICERR_SendMsg()
  1357. {
  1358. L_AI_SendMsg(false, 0, 0, 0);
  1359. }
  1360. //
  1361. // Logic I_OFFICERB
  1362. //
  1363. void L_I_OFFICERB_SetupLogic()
  1364. {
  1365. L_AI_SetupLogic();
  1366. }
  1367. void L_I_OFFICERB_SetupObj()
  1368. {
  1369. L_AI_SetupObj(10, AI_State_Look, 0, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_None);
  1370. }
  1371. void L_I_OFFICERB_Update()
  1372. {
  1373. if ( L_AI_RunAIState(-1, 0) == 1 )
  1374. {
  1375. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "IKEYB.FME", "BLUE", 0);
  1376. }
  1377. }
  1378. void L_I_OFFICERB_SendMsg()
  1379. {
  1380. L_AI_SendMsg(false, 0, 0, 0);
  1381. }
  1382. //
  1383. // Logic I_OFFICERY
  1384. //
  1385. void L_I_OFFICERY_SetupLogic()
  1386. {
  1387. L_AI_SetupLogic();
  1388. }
  1389. void L_I_OFFICERY_SetupObj()
  1390. {
  1391. L_AI_SetupObj(10, AI_State_Look, 0, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_None);
  1392. }
  1393. void L_I_OFFICERY_Update()
  1394. {
  1395. if ( L_AI_RunAIState(-1, 0) == 1 )
  1396. {
  1397. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "IKEYY.FME", "YELLOW", 0);
  1398. }
  1399. }
  1400. void L_I_OFFICERY_SendMsg()
  1401. {
  1402. L_AI_SendMsg(false, 0, 0, 0);
  1403. }
  1404. //
  1405. // Logic I_OFFICER1
  1406. //
  1407. void L_I_OFFICER1_SetupLogic()
  1408. {
  1409. L_AI_SetupLogic();
  1410. }
  1411. void L_I_OFFICER1_SetupObj()
  1412. {
  1413. L_AI_SetupObj(10, AI_State_Look, 0, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_None);
  1414. }
  1415. void L_I_OFFICER1_Update()
  1416. {
  1417. if ( L_AI_RunAIState(-1, 0) == 1 )
  1418. {
  1419. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "DET_CODE.FME", "CODE1", 0);
  1420. }
  1421. }
  1422. void L_I_OFFICER1_SendMsg()
  1423. {
  1424. L_AI_SendMsg(false, 0, 0, 0);
  1425. }
  1426. //
  1427. // Logic I_OFFICER2
  1428. //
  1429. void L_I_OFFICER2_SetupLogic()
  1430. {
  1431. L_AI_SetupLogic();
  1432. }
  1433. void L_I_OFFICER2_SetupObj()
  1434. {
  1435. L_AI_SetupObj(10, AI_State_Look, 0, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_None);
  1436. }
  1437. void L_I_OFFICER2_Update()
  1438. {
  1439. if ( L_AI_RunAIState(-1, 0) == 1 )
  1440. {
  1441. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "DET_CODE.FME", "CODE2", 0);
  1442. }
  1443. }
  1444. void L_I_OFFICER2_SendMsg()
  1445. {
  1446. L_AI_SendMsg(false, 0, 0, 0);
  1447. }
  1448. //
  1449. // Logic I_OFFICER3
  1450. //
  1451. void L_I_OFFICER3_SetupLogic()
  1452. {
  1453. L_AI_SetupLogic();
  1454. }
  1455. void L_I_OFFICER3_SetupObj()
  1456. {
  1457. L_AI_SetupObj(10, AI_State_Look, 0, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_None);
  1458. }
  1459. void L_I_OFFICER3_Update()
  1460. {
  1461. if ( L_AI_RunAIState(-1, 0) == 1 )
  1462. {
  1463. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "DET_CODE.FME", "CODE3", 0);
  1464. }
  1465. }
  1466. void L_I_OFFICER3_SendMsg()
  1467. {
  1468. L_AI_SendMsg(false, 0, 0, 0);
  1469. }
  1470. //
  1471. // Logic I_OFFICER4
  1472. //
  1473. void L_I_OFFICER4_SetupLogic()
  1474. {
  1475. L_AI_SetupLogic();
  1476. }
  1477. void L_I_OFFICER4_SetupObj()
  1478. {
  1479. L_AI_SetupObj(10, AI_State_Look, 0, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_None);
  1480. }
  1481. void L_I_OFFICER4_Update()
  1482. {
  1483. if ( L_AI_RunAIState(-1, 0) == 1 )
  1484. {
  1485. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "DET_CODE.FME", "CODE4", 0);
  1486. }
  1487. }
  1488. void L_I_OFFICER4_SendMsg()
  1489. {
  1490. L_AI_SendMsg(false, 0, 0, 0);
  1491. }
  1492. //
  1493. // Logic I_OFFICER5
  1494. //
  1495. void L_I_OFFICER5_SetupLogic()
  1496. {
  1497. L_AI_SetupLogic();
  1498. }
  1499. void L_I_OFFICER5_SetupObj()
  1500. {
  1501. L_AI_SetupObj(10, AI_State_Look, 0, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_None);
  1502. }
  1503. void L_I_OFFICER5_Update()
  1504. {
  1505. if ( L_AI_RunAIState(-1, 0) == 1 )
  1506. {
  1507. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "DET_CODE.FME", "CODE5", 0);
  1508. }
  1509. }
  1510. void L_I_OFFICER5_SendMsg()
  1511. {
  1512. L_AI_SendMsg(false, 0, 0, 0);
  1513. }
  1514. //
  1515. // Logic I_OFFICER6
  1516. //
  1517. void L_I_OFFICER6_SetupLogic()
  1518. {
  1519. L_AI_SetupLogic();
  1520. }
  1521. void L_I_OFFICER6_SetupObj()
  1522. {
  1523. L_AI_SetupObj(10, AI_State_Look, 0, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_None);
  1524. }
  1525. void L_I_OFFICER6_Update()
  1526. {
  1527. if ( L_AI_RunAIState(-1, 0) == 1 )
  1528. {
  1529. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "DET_CODE.FME", "CODE6", 0);
  1530. }
  1531. }
  1532. void L_I_OFFICER6_SendMsg()
  1533. {
  1534. L_AI_SendMsg(false, 0, 0, 0);
  1535. }
  1536. //
  1537. // Logic I_OFFICER7
  1538. //
  1539. void L_I_OFFICER7_SetupLogic()
  1540. {
  1541. L_AI_SetupLogic();
  1542. }
  1543. void L_I_OFFICER7_SetupObj()
  1544. {
  1545. L_AI_SetupObj(10, AI_State_Look, 0, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_None);
  1546. }
  1547. void L_I_OFFICER7_Update()
  1548. {
  1549. if ( L_AI_RunAIState(-1, 0) == 1 )
  1550. {
  1551. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "DET_CODE.FME", "CODE7", 0);
  1552. }
  1553. }
  1554. void L_I_OFFICER7_SendMsg()
  1555. {
  1556. L_AI_SendMsg(false, 0, 0, 0);
  1557. }
  1558. //
  1559. // Logic I_OFFICER8
  1560. //
  1561. void L_I_OFFICER8_SetupLogic()
  1562. {
  1563. L_AI_SetupLogic();
  1564. }
  1565. void L_I_OFFICER8_SetupObj()
  1566. {
  1567. L_AI_SetupObj(10, AI_State_Look, 0, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_None);
  1568. }
  1569. void L_I_OFFICER8_Update()
  1570. {
  1571. if ( L_AI_RunAIState(-1, 0) == 1 )
  1572. {
  1573. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "DET_CODE.FME", "CODE8", 0);
  1574. }
  1575. }
  1576. void L_I_OFFICER8_SendMsg()
  1577. {
  1578. L_AI_SendMsg(false, 0, 0, 0);
  1579. }
  1580. //
  1581. // Logic I_OFFICER9
  1582. //
  1583. void L_I_OFFICER9_SetupLogic()
  1584. {
  1585. L_AI_SetupLogic();
  1586. }
  1587. void L_I_OFFICER9_SetupObj()
  1588. {
  1589. L_AI_SetupObj(10, AI_State_Look, 0, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_None);
  1590. }
  1591. void L_I_OFFICER9_Update()
  1592. {
  1593. if ( L_AI_RunAIState(-1, 0) == 1 )
  1594. {
  1595. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "DET_CODE.FME", "CODE9", 0);
  1596. }
  1597. }
  1598. void L_I_OFFICER9_SendMsg()
  1599. {
  1600. L_AI_SendMsg(false, 0, 0, 0);
  1601. }
  1602. //
  1603. // Logic COMMANDO
  1604. //
  1605. void L_COMMANDO_SetupLogic()
  1606. {
  1607. L_AI_SetupLogic();
  1608. }
  1609. void L_COMMANDO_SetupObj()
  1610. {
  1611. L_AI_SetupObj(30, AI_State_Look, 1, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_Allow_Double_Shoot);
  1612. }
  1613. void L_COMMANDO_Update()
  1614. {
  1615. if ( L_AI_RunAIState(-1, 0) == 1 )
  1616. {
  1617. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "IST-GUNI.FME", "RIFLE", 0);
  1618. }
  1619. }
  1620. void L_COMMANDO_SendMsg()
  1621. {
  1622. L_AI_SendMsg(false, 0, 0, 0);
  1623. }
  1624. //
  1625. // Logic BOSSK
  1626. //
  1627. void L_BOSSK_SetupLogic()
  1628. {
  1629. L_AI_SetupLogic();
  1630. }
  1631. void L_BOSSK_SetupObj()
  1632. {
  1633. L_AI_SetupObj(50, AI_State_Look, 1, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_ShootExp);
  1634. }
  1635. void L_BOSSK_Update()
  1636. {
  1637. if ( L_AI_RunAIState(-1, 0) == 1 )
  1638. {
  1639. //if ( !Obj_In_Water() ) Map_AddObject("FRAME", "IST-GUNI.FME", "RIFLE", 0);
  1640. }
  1641. }
  1642. void L_BOSSK_SendMsg()
  1643. {
  1644. L_AI_SendMsg(false, 7, 4, 5);
  1645. }
  1646. //
  1647. // Logic INT_DROID
  1648. //
  1649. void L_INT_DROID_SetupLogic()
  1650. {
  1651. L_AI_SetupLogic();
  1652. }
  1653. void L_INT_DROID_SetupObj()
  1654. {
  1655. L_AI_SetupObj(50, AI_State_Look, 1, 0, Anim_Sec_Attack, Anim_Attacking, true, AI_Flags_Floating|AI_Flags_Has_Melee);
  1656. Obj_SetProjectileData("SPRITE", "WIDBALL.WAX", "WEMISS.WAX", "PROBFIR1.VOC", "EX-TINY1.VOC", 8, 0.0);
  1657. }
  1658. void L_INT_DROID_Update()
  1659. {
  1660. if ( L_AI_RunAIState(0, 5) == 1 )
  1661. {
  1662. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "IPOWER.FME", "POWER", 0);
  1663. }
  1664. }
  1665. void L_INT_DROID_SendMsg()
  1666. {
  1667. L_AI_SendMsg(false, 1, -1, 1);
  1668. }
  1669. //
  1670. // Logic PROBE_DROID
  1671. //
  1672. void L_PROBE_DROID_SetupLogic()
  1673. {
  1674. L_AI_SetupLogic();
  1675. }
  1676. void L_PROBE_DROID_SetupObj()
  1677. {
  1678. L_AI_SetupObj(50, AI_State_Look, 1, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_Floating|AI_Flags_Allow_Double_Shoot);
  1679. Obj_SetLocalVar(AI_Min_Reaction, Sprite_GetFrameCnt(Anim_Moving, 0)*7);
  1680. }
  1681. void L_PROBE_DROID_Update()
  1682. {
  1683. ceil_dist = 10.0f;
  1684. if ( L_AI_RunAIState(-1, 0) == 1 )
  1685. {
  1686. if ( !Obj_In_Water() )
  1687. {
  1688. float ground_height = Map_GetFloorHeight(0, -1);
  1689. if ( obj_loc_z < ground_height+1.0f )
  1690. Map_AddObject("FRAME", "IPOWER.FME", "POWER", 0);
  1691. }
  1692. }
  1693. ceil_dist = 5.0f;
  1694. }
  1695. void L_PROBE_DROID_SendMsg()
  1696. {
  1697. bool bJustDied = L_AI_SendMsg(false, 2, -1, 2);
  1698. //this enemy explodes after it dies...
  1699. if ( bJustDied )
  1700. {
  1701. //x, y, z, radius, damage, delay, scale, graphic (sprite), sound
  1702. Map_AddExplosion(obj_loc_x, obj_loc_y, Map_GetFloorHeight(0, -1), 10.0f, 20.0f, 1.0f, 0.5f, "MINEEXP.WAX", "EX-SMALL.VOC", false, -1);
  1703. }
  1704. }
  1705. //
  1706. // Logic REMOTE
  1707. //
  1708. void L_REMOTE_SetupLogic()
  1709. {
  1710. //we don't want standard alerts, this unit acts the same even if no players are present.
  1711. //Logic_AddMsgMask(MSG_NRML_DAMAGE);
  1712. //Logic_AddMsgMask(MSG_MELEE_DAMAGE);
  1713. }
  1714. void L_REMOTE_SetupObj()
  1715. {
  1716. //L_AI_SetupObj(20, AI_State_Remote|AI_State_Transition, 1, 0, Anim_Attacking, Anim_Sec_Attack, true, AI_Flags_Floating|AI_Flags_NoAlert);
  1717. //obj_Speed = 1.0f;
  1718. Obj_SetFlag(OFLAGS_INVISIBLE);
  1719. }
  1720. void L_REMOTE_Update()
  1721. {
  1722. /*
  1723. if ( L_AI_RunAIState(-1, 0) == 1 )
  1724. {
  1725. if ( !Obj_In_Water() ) Map_AddObject("FRAME", "IPOWER.FME", "POWER", 0);
  1726. }
  1727. */
  1728. }
  1729. void L_REMOTE_SendMsg()
  1730. {
  1731. //L_AI_SendMsg(false, 3, -1, 3);
  1732. }
  1733. //
  1734. // SEWER1
  1735. //
  1736. void L_SEWER1_SetupLogic()
  1737. {
  1738. //we don't want standard alerts, this unit acts the same even if no players are present.
  1739. Logic_AddMsgMask(MSG_NRML_DAMAGE);
  1740. Logic_AddMsgMask(MSG_MELEE_DAMAGE);
  1741. }
  1742. void L_SEWER1_SetupObj()
  1743. {
  1744. L_AI_SetupObj(30, AI_State_Wander_UG|AI_State_Transition, 1, 0, Anim_Moving, Anim_Attacking, true, AI_Flags_Has_Melee | AI_Flags_SingleAttckOnly | AI_Flags_NoRangeAttck | AI_Flags_Underground | AI_Flags_FloatOnWater);
  1745. obj_Speed = 0.1f;
  1746. }
  1747. void L_SEWER1_Update()
  1748. {
  1749. if ( L_AI_RunAIState(1, 20) == 1 )
  1750. {
  1751. //sewer bugs don't l…

Large files files are truncated, but you can click here to view the full file