Advertisement
Pr0nogo

Untitled

Jul 30th, 2018
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.69 KB | None | 0 0
  1. #include "recall_spell.h"
  2. #include <SCBW/api.h>
  3.  
  4. //helper functions def
  5.  
  6. namespace {
  7.  
  8. bool setThingyVisibilityFlags(CThingy* thingy); //0x004878F0
  9. CThingy* createThingy(u32 spriteId, s16 x, s16 y, u32 playerId); //0x00488210
  10. void setUnitStatTxtErrorMsg(char* message); //0x0048CCB0
  11. void playUnitSFX(u32 soundId, u16 x, u16 y, u32 unk1, u32 unk2); //0x0048EC10
  12. u32 RandomizeShort(u32 unknown_index); //0x004DC4A0
  13. u32 IterateUnitsAtLocationTargetProc_RecallTargets(CUnit* unit, Box16* coords); //0x004E8280
  14. void function_004EBAE0(CUnit* unit, s32 x, s32 y); //0x004EBAE0
  15.  
  16. } //unnamed namespace
  17.  
  18. namespace hooks {
  19.  
  20. //Originally known as sub_4942D0
  21. //Function performed on each target of Recall
  22. //by IterateUnitsAtLocationTargetProc_RecallTargets
  23. //that was validated throug spells_Recall_ActionOnTargetInRange
  24. //Do the actual unit movement
  25. void spells_Recall_ActionOnValidTargetForRecall(CUnit* target, CUnit* caster) {
  26.  
  27. static Bool32* const bAtLeast1UnitWasRecalled = (Bool32*)(0x0063FF50);
  28.  
  29. /*Point16 previous_pos, new_pos;
  30.  
  31. previous_pos.x = target->sprite->position.x;
  32. previous_pos.y = target->sprite->position.y;
  33.  
  34. //identical code to setUnitPosition() but for some reason, is
  35. //using another function to do exactly the same thing
  36. function_004EBAE0(target,caster->sprite->position.x,caster->sprite->position.y);
  37.  
  38. if(!scbw::checkUnitCollisionPos(target,&(caster->sprite->position),&new_pos,NULL,false,0))
  39. //collision detected, cancel the movement
  40. scbw::setUnitPosition(target,previous_pos.x,previous_pos.y);
  41. else {*/
  42.  
  43. CThingy* recall_effect_sprite;
  44. target->userActionFlags |= 0x4;
  45. target->remove();
  46.  
  47. /*//finish the teleporting (and cut the recalled unit from a possible unit targeted by an order)
  48. scbw::prepareUnitMove(target,false);
  49. target->orderTarget.unit = NULL;
  50. scbw::setUnitPosition(target,new_pos.x,new_pos.y);
  51. scbw::refreshUnitAfterMove(target);
  52.  
  53. //stop some currently active orders
  54. if(target->id != UnitId::ZergCocoon)
  55. target->orderComputerCL(units_dat::ReturnToIdleOrder[target->id]);
  56.  
  57. //create the Recall animation over the unit
  58. recall_effect_sprite = createThingy(SpriteId::Recall_Field,new_pos.x,new_pos.y,0);
  59. if(recall_effect_sprite != NULL) {
  60. recall_effect_sprite->sprite->elevationLevel = target->sprite->elevationLevel + 1;
  61. setThingyVisibilityFlags(recall_effect_sprite);
  62. }
  63.  
  64. //disconnect a nuke from a ghost using it
  65. if(
  66. target->id == UnitId::TerranGhost ||
  67. target->id == UnitId::Hero_SarahKerrigan ||
  68. target->id == UnitId::Hero_AlexeiStukov ||
  69. target->id == UnitId::Hero_SamirDuran ||
  70. target->id == UnitId::Hero_InfestedDuran
  71. )
  72. {
  73.  
  74. if(
  75. target->connectedUnit != NULL &&
  76. target->connectedUnit->id == UnitId::TerranNuclearMissile
  77. )
  78. {
  79. (target->connectedUnit)->connectedUnit = NULL;
  80. target->connectedUnit = NULL;
  81. }
  82.  
  83. }*/
  84.  
  85. *bAtLeast1UnitWasRecalled = 1;
  86.  
  87. }
  88.  
  89. } //void spells_Recall_ActionOnValidTargetForRecall(CUnit* target, CUnit* caster)
  90.  
  91. ;
  92.  
  93. //Originally known as sub_494400
  94. //Function performed on each target of Recall
  95. //by IterateUnitsAtLocationTargetProc_RecallTargets
  96. //to choose if the unit can have the Recall effect
  97. //cast on it or no, and if yes, calling another function
  98. //to do the Recall effect.
  99. void spells_Recall_ActionOnTargetInRange(CUnit* target, CUnit* caster) {
  100.  
  101. if(
  102. !(target->sprite->flags & CSprite_Flags::Hidden) &&
  103. //target->playerId == caster->playerId &&
  104. //!(units_dat::BaseProperty[target->id] & UnitProperty::Building) &&
  105. !(target->status & UnitStatus::Invincible) &&
  106. !(target->status & UnitStatus::Burrowed) &&
  107. target->id != UnitId::ZergLarva &&
  108. target->id != UnitId::ZergEgg &&
  109. target->id != UnitId::ZergLurkerEgg &&
  110. target->id != UnitId::infested_kerrigan &&
  111. //!(target->status & UnitStatus::IsHallucination) &&
  112. target != caster
  113. )
  114. spells_Recall_ActionOnValidTargetForRecall(target,caster);
  115.  
  116. }
  117.  
  118. ;
  119.  
  120. void orders_Recall(CUnit* unit) {
  121.  
  122. static Bool32* const bAtLeast1UnitWasRecalled = (Bool32*)(0x0063FF50);
  123.  
  124. //unit has started casting Recall (== went through the other condition)
  125. if(unit->mainOrderState == 1) {
  126.  
  127. //execute the recall effect when timer reach 0
  128. if(unit->mainOrderTimer == 0) {
  129.  
  130. Box16 spell_location;
  131.  
  132. spell_location.left = unit->orderTarget.pt.x - 64;
  133. spell_location.top = unit->orderTarget.pt.y - 64;
  134. spell_location.right = unit->orderTarget.pt.x + 64;
  135. spell_location.bottom = unit->orderTarget.pt.y + 64;
  136.  
  137. *bAtLeast1UnitWasRecalled = 0;
  138.  
  139. //apply the recal effect on each valid target found in spell_location
  140. scbw::playSound(SoundId::Protoss_ARBITER_PAbFol03_WAV, unit);
  141. //IterateUnitsAtLocationTargetProc_RecallTargets(unit,&spell_location);
  142.  
  143. if(*bAtLeast1UnitWasRecalled != 0) {
  144.  
  145. //original code added (RandomizeShort(0x12) & 1) to the base sound
  146. //id Protoss_ARBITER_PAbFol02_WAV then called the playSound function
  147. //using that value, but since there are only 2 sounds, it's easier to
  148. //see what sound is used that way.
  149. //The compiler may make it back like the original anyway.
  150.  
  151. /*if((RandomizeShort(0x12) & 1) == 0)
  152. scbw::playSound(SoundId::Protoss_ARBITER_PAbFol02_WAV,unit);
  153. else
  154. scbw::playSound(SoundId::Protoss_ARBITER_PAbFol03_WAV,unit);*/
  155.  
  156. }
  157.  
  158. unit->orderToIdle();
  159.  
  160. }
  161.  
  162. }
  163. else { //94505
  164.  
  165. if(
  166. !scbw::isCheatEnabled(CheatFlags::TheGathering) &&
  167. unit->energy < techdata_dat::EnergyCost[TechId::Recall] * 256
  168. )
  169. {
  170.  
  171. u8 raceId;
  172. char* message;
  173.  
  174. if(units_dat::GroupFlags[unit->id].isZerg)
  175. raceId = RaceId::Zerg;
  176. else
  177. if(units_dat::GroupFlags[unit->id].isTerran)
  178. raceId = RaceId::Terran;
  179. else
  180. if(units_dat::GroupFlags[unit->id].isProtoss)
  181. raceId = RaceId::Protoss;
  182. else
  183. raceId = RaceId::Neutral;
  184.  
  185. message = (char*)statTxtTbl->getString(864 + raceId); //"Not enough energy" text
  186.  
  187. if(
  188. message != NULL &&
  189. unit->playerId == *LOCAL_NATION_ID &&
  190. *ACTIVE_PLAYER_ID == *LOCAL_HUMAN_ID
  191. )
  192. setUnitStatTxtErrorMsg(message);
  193.  
  194. unit->orderToIdle();
  195.  
  196. }
  197. else { //945B9
  198.  
  199. CThingy* recall_effect_sprite;
  200. u32 random_value;
  201.  
  202. if(!scbw::isCheatEnabled(CheatFlags::TheGathering))
  203. unit->energy -= techdata_dat::EnergyCost[TechId::Recall] * 256;
  204.  
  205. if(unit->orderTarget.unit != NULL) {
  206. unit->orderTarget.pt.x = unit->orderTarget.unit->sprite->position.x;
  207. unit->orderTarget.pt.y = unit->orderTarget.unit->sprite->position.y;
  208. }
  209.  
  210. recall_effect_sprite =
  211. createThingy(
  212. SpriteId::Recall_Field,
  213. unit->orderTarget.pt.x,
  214. unit->orderTarget.pt.y,
  215. 0
  216. );
  217.  
  218. if(recall_effect_sprite != NULL) {
  219. recall_effect_sprite->sprite->elevationLevel = unit->sprite->elevationLevel + 1;
  220. setThingyVisibilityFlags(recall_effect_sprite);
  221. }
  222.  
  223. //94617
  224. if(*IS_IN_GAME_LOOP) {
  225.  
  226. //hardcoded (not using a function) RNG use, like
  227. //the original code do
  228.  
  229. static u32* const u32_0051C654 = (u32*)0x0051C654;
  230. static u32* const u32_0051CA18 = (u32*)0x0051CA18;
  231.  
  232. *u32_0051C654 = *u32_0051C654 + 1;
  233. *u32_0051CA18 = *u32_0051CA18 + 1;
  234. *lastRandomNumber = (*lastRandomNumber * 0x015A4E35) + 1;
  235.  
  236. random_value = ((*lastRandomNumber) / 65536) & 0x7FFF;
  237.  
  238. }
  239. else
  240. random_value = 0;
  241.  
  242. //original code added (random_value & 1) to the base sound
  243. //id Protoss_ARBITER_PAbFol00_WAV then called the playSound function
  244. //using that value, but since there are only 2 sounds, it's easier to
  245. //see what sound is used that way.
  246. //The compiler may make it back like the original anyway.
  247.  
  248. if((random_value & 1) == 0)
  249. playUnitSFX(
  250. SoundId::Protoss_ARBITER_PAbFol00_WAV,
  251. unit->orderTarget.pt.x,
  252. unit->orderTarget.pt.y,
  253. 1,
  254. 0
  255. );
  256. else
  257. playUnitSFX(
  258. SoundId::Protoss_ARBITER_PAbFol01_WAV,
  259. unit->orderTarget.pt.x,
  260. unit->orderTarget.pt.y,
  261. 1,
  262. 0
  263. );
  264.  
  265. unit->mainOrderTimer = 22;
  266. unit->mainOrderState = 1;
  267.  
  268. }
  269.  
  270. }
  271.  
  272. } //void orders_Recall(CUnit* unit)
  273. //namespace hooks
  274.  
  275. //-------- Helper function definitions. Do NOT modify! --------//
  276.  
  277. namespace {
  278.  
  279. //original referenced name was sub_4878F0, but using
  280. //the name from bunker_hooks.cpp since it got meaning
  281. const u32 Func_SetThingyVisibilityFlags = 0x004878F0;
  282. bool setThingyVisibilityFlags(CThingy* thingy) {
  283.  
  284. static Bool32 bPreResult;
  285.  
  286. __asm {
  287. PUSHAD
  288. MOV ESI, thingy
  289. CALL Func_SetThingyVisibilityFlags
  290. MOV bPreResult, EAX
  291. POPAD
  292. }
  293.  
  294. return (bPreResult != 0);
  295.  
  296. }
  297.  
  298. ;
  299.  
  300. //original referenced name was replaceSprite (but this one is probably
  301. //more accurate since it does create something rather than replacing)
  302. const u32 Func_CreateThingy = 0x00488210;
  303. CThingy* createThingy(u32 spriteId, s16 x, s16 y, u32 playerId) {
  304.  
  305. static CThingy* thingy;
  306. s32 x_ = x;
  307.  
  308. __asm {
  309. PUSHAD
  310. PUSH playerId
  311. MOVSX EDI, y
  312. PUSH x_
  313. PUSH spriteId
  314. CALL Func_CreateThingy
  315. MOV thingy, EAX
  316. POPAD
  317. }
  318.  
  319. return thingy;
  320.  
  321. }
  322.  
  323. ;
  324.  
  325. const u32 Func_playUnitSFX = 0x0048EC10;
  326. void playUnitSFX(u32 soundId, u16 x, u16 y, u32 unk1, u32 unk2) {
  327.  
  328. static Point16 pos;
  329.  
  330. pos.x = x;pos.y = y;
  331.  
  332. __asm {
  333. PUSHAD
  334. PUSH unk2
  335. PUSH unk1
  336. PUSH pos
  337. MOV EBX, soundId
  338. CALL Func_playUnitSFX
  339. POPAD
  340. }
  341.  
  342. }
  343.  
  344. ;
  345.  
  346. const u32 Func_RandomizeShort = 0x004DC4A0;
  347. u32 RandomizeShort(u32 unknown_index) {
  348.  
  349. static u32 return_value;
  350.  
  351. __asm {
  352. PUSHAD
  353. MOV EAX, unknown_index
  354. CALL Func_RandomizeShort
  355. MOV return_value, EAX
  356. POPAD
  357. }
  358.  
  359. return return_value;
  360.  
  361. }
  362.  
  363. ;
  364.  
  365. const u32 Func_IterateUnitsAtLocationTargetProc = 0x004E8280;
  366. //hardcoding the recall targets selection function
  367. u32 IterateUnitsAtLocationTargetProc_RecallTargets(CUnit* unit, Box16* coords) {
  368.  
  369. static u32 return_value;
  370.  
  371. __asm {
  372. PUSHAD
  373. PUSH unit
  374. MOV EAX, coords
  375. MOV EBX, 0x00494400
  376. CALL Func_IterateUnitsAtLocationTargetProc
  377. MOV return_value, EAX
  378. POPAD
  379. }
  380.  
  381. return return_value;
  382.  
  383. }
  384.  
  385. ;
  386.  
  387. const u32 Func_setUnitStatTxtErrorMsg = 0x0048CCB0;
  388. void setUnitStatTxtErrorMsg(char* message) {
  389.  
  390. __asm {
  391. PUSHAD
  392. MOV EAX, message
  393. CALL Func_setUnitStatTxtErrorMsg
  394. POPAD
  395. }
  396.  
  397. }
  398.  
  399. ;
  400.  
  401. const u32 Func_Sub4EBAE0 = 0x004EBAE0;
  402. void function_004EBAE0(CUnit* unit, s32 x, s32 y) {
  403.  
  404. __asm {
  405. PUSHAD
  406. MOV EDX, unit
  407. MOV EAX, x
  408. MOV ECX, y
  409. CALL Func_Sub4EBAE0
  410. POPAD
  411. }
  412.  
  413. }
  414.  
  415. ;
  416.  
  417. } //Unnamed namespace
  418.  
  419. //End of helper functions
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement