Toolkit_Powerup.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /******************************************************************************
  19. *
  20. * FILE
  21. * Toolkit_Powerup.cpp
  22. *
  23. * DESCRIPTION
  24. * Designer Toolkit for Mission Construction - Powerup Manager
  25. *
  26. * PROGRAMMER
  27. * Design Team
  28. *
  29. * VERSION INFO
  30. * $Author: Rich_d $
  31. * $Revision: 28 $
  32. * $Modtime: 2/18/02 4:41p $
  33. * $Archive: /Commando/Code/Scripts/Toolkit_Powerup.cpp $
  34. *
  35. ******************************************************************************/
  36. #include "toolkit.h"
  37. // The Soldier Powerup Tables contains three columns.
  38. // The first chars of the preset name, the weapon powerup, and the twiddler powerup.
  39. // The first preset name match is used.
  40. #define POWERUP_TABLE_SIZE ( sizeof(Soldier_Powerup_Table) / sizeof (Soldier_Powerup_Table[0]) )
  41. const char * Soldier_Powerup_Table[][3] = {
  42. { "Mutant_0_Mutant", "tw_POW00_Armor", "tw_POW00_Armor" },
  43. { "Mutant_1Off_Acolyte", "POW_TiberiumAutoRifle_Player", "tw_POW02_LaserRifle" },
  44. { "Mutant_2SF_Templar", "POW_TiberiumAutoRifle_Player", "tw_POW01_TiberiumAutoRifle"},
  45. { "Nod_FlameThrower_2SF", "POW_LaserRifle_Player", "tw_POW02_LaserRifle" },
  46. { "Nod_FlameThrower_1Off", "POW_ChemSprayer_Player", "tw_POW01_Chemsprayer" },
  47. { "Nod_FlameThrower_0", "POW_Flamethrower_Player", "tw_POW00_Flamethrower" },
  48. { "Nod_Minigunner_0", "POW_AutoRifle_Player", "tw_POW00_AutoRifle" },
  49. { "Nod_Minigunner_1Off_LaserChaingun", "POW_LaserChaingun_Player", "tw_POW01_LaserChaingun" },
  50. { "Nod_Minigunner_1Off_Shotgun", "tw_POW00_Health", "tw_POW00_Health" },
  51. { "Nod_Minigunner_1Off", "POW_Chaingun_Player", "tw_POW01_Chaingun" },
  52. { "Nod_Minigunner_2SF_AutoRifle", "POW_AutoRifle_Player", "tw_POW02_AutoRifle" },
  53. { "Nod_Minigunner_2SF_Chaingun", "POW_Chaingun_Player", "tw_POW02_Chaingun" },
  54. { "Nod_Minigunner_2SF_Ramjet", "POW_RamjetRifle_Player", "tw_POW02_RamjetRifle" },
  55. { "Nod_Minigunner_2SF_Stationary", "POW_SniperRifle_Player", "tw_POW02_SniperRifle" },
  56. { "Nod_Minigunner_2SF_Shotgun", "tw_POW00_Health", "tw_POW02_SniperRifle" },
  57. { "Nod_Minigunner_2SF_LaserRifle", "tw_POW00_Health", "tw_POW00_Health" },
  58. { "Nod_Minigunner_2SF", "POW_SniperRifle_Player", "tw_POW00_Health" },
  59. { "Nod_RocketSoldier_2SF_AutoRifle", "POW_AutoRifle_Player", "tw_POW02_AutoRifle" },
  60. { "Nod_RocketSoldier_2SF_Chaingun", "POW_Chaingun_Player", "tw_POW02_Chaingun" },
  61. { "Nod_RocketSoldier_2SF_VoltAutoRifle", "POW_VoltAutoRifle_Player", "tw_POW02_VoltAutoRifle" },
  62. { "Nod_RocketSoldier_2SF_LaserRifle", "tw_POW00_Health", "tw_POW00_Health" },
  63. { "Nod_RocketSoldier", "POW_RocketLauncher_Player", "tw_POW00_RocketLauncher" },
  64. { "", "tw_POW00_Health", "tw_POW00_Health" }, // Last entry is the catch-all
  65. };
  66. DECLARE_SCRIPT(M00_Soldier_Powerup_Grant, "")
  67. {
  68. bool Disabled; // Has this script been disabled (usually for a custom override)
  69. // Register variables to be Auto-Saved
  70. // All variables must have a unique ID, less than 256, that never changes
  71. REGISTER_VARIABLES()
  72. {
  73. SAVE_VARIABLE( Disabled, 1 );
  74. }
  75. void Created(GameObject* obj)
  76. {
  77. Disabled = false; // Default to enabled
  78. }
  79. // Find the index of the first matching sub name
  80. int Find_Powerup_Table_Index( const char * name )
  81. {
  82. for ( int i = 0; i < POWERUP_TABLE_SIZE; i++ ) {
  83. const char * test_name = Soldier_Powerup_Table[i][0];
  84. if ( ::strncmp( test_name, name, ::strlen( test_name ) ) == 0 ) {
  85. return i;
  86. }
  87. }
  88. Commands->Debug_Message( "Soldier_Powerup_Grant failed to find name match %s\n", name );
  89. return 0;
  90. }
  91. // When killed, drop a powerup
  92. void Killed (GameObject * obj, GameObject * killer)
  93. {
  94. // We only drop a powerup if our killer is a star
  95. // 100% for Easy
  96. // 67% for Medium
  97. // 33% for Hard
  98. if( !Disabled && killer && Commands->Is_A_Star(killer) && (Commands->Get_Random_Int(0, 3) >= Commands->Get_Difficulty_Level()))
  99. {
  100. // Find the destoyed object's preset name
  101. const char * preset_name = Commands->Get_Preset_Name( obj );
  102. Commands->Debug_Message( "Soldier_Powerup_Grant for %s\n", preset_name );
  103. // Find the index of this object
  104. int index = Find_Powerup_Table_Index( preset_name );
  105. Commands->Debug_Message( "Soldier_Powerup_Grant: index %d\n", index );
  106. // Calculate the star's health percentage
  107. float star_health = Commands->Get_Health( killer );
  108. float star_health_max = Commands->Get_Max_Health( killer );
  109. float star_health_percent = 0;
  110. if ( star_health_max ) {
  111. star_health_percent = star_health / star_health_max;
  112. }
  113. // Calculate the star's shield percentage
  114. float star_shield = Commands->Get_Shield_Strength( killer );
  115. float star_shield_max = Commands->Get_Max_Shield_Strength( killer );
  116. float star_shield_percent = 0;
  117. if ( star_shield_max ) {
  118. star_shield_percent = star_shield / star_shield_max;
  119. }
  120. // Calcutate a powerup spawn point
  121. Vector3 spawn_spot = Commands->Get_Position ( obj );
  122. spawn_spot.Z += 0.75f; // Bump it up a bit
  123. GameObject * powerup = NULL;
  124. // If star's health < 25%, drop health
  125. if ( star_health_percent < 0.25f ) {
  126. Commands->Debug_Message( "Soldier_Powerup_Grant: Star's Health < 25%%. Dropping Health\n" );
  127. powerup = Commands->Create_Object ( "tw_POW00_Health", spawn_spot );
  128. }
  129. // If star's shield < 25%, drop shield
  130. if ( powerup == NULL && star_shield_percent < 0.25f ) {
  131. Commands->Debug_Message( "Soldier_Powerup_Grant: Star's Shield < 25%%. Dropping Sheild\n" );
  132. powerup = Commands->Create_Object ( "tw_POW00_Armor", spawn_spot );
  133. }
  134. // If star's health > 75%, drop weapon
  135. if ( powerup == NULL && star_health_percent > 0.75f ) {
  136. const char * weapon_powerup = Soldier_Powerup_Table[index][1];
  137. if ( weapon_powerup != NULL && weapon_powerup[0] != 0 ) {
  138. Commands->Debug_Message( "Soldier_Powerup_Grant: Star's Health > 75%%. Dropping soldier's weapon %s\n", weapon_powerup );
  139. powerup = Commands->Create_Object ( weapon_powerup, spawn_spot );
  140. }
  141. }
  142. // Drop soldier's twiddler
  143. if ( powerup == NULL ) {
  144. const char * twiddler = Soldier_Powerup_Table[index][2];
  145. if ( twiddler != NULL && twiddler[0] != 0 ) {
  146. Commands->Debug_Message( "Soldier_Powerup_Grant: Dropping twiddler %s\n", twiddler );
  147. powerup = Commands->Create_Object ( twiddler, spawn_spot );
  148. }
  149. }
  150. // It we created a powerup, give it the powerup script
  151. if ( powerup != NULL ) {
  152. Commands->Attach_Script( powerup, "M00_Powerup_Destroy", "");
  153. }
  154. }
  155. }
  156. // Custom to disable this script
  157. void Custom( GameObject * obj, int type, int param, GameObject * sender )
  158. {
  159. if ( type == M00_CUSTOM_POWERUP_GRANT_DISABLE ) {
  160. Disabled = true;
  161. }
  162. }
  163. };
  164. // DAY - Attach to disable powerup manager on an instance or preset
  165. DECLARE_SCRIPT(M00_Soldier_Powerup_Disable, "")
  166. {
  167. void Created (GameObject * obj)
  168. {
  169. Commands->Start_Timer(obj, this, 1.0f, 1);
  170. }
  171. void Timer_Expired(GameObject * obj, int timer_id)
  172. {
  173. if (timer_id == 1)
  174. {
  175. Commands->Send_Custom_Event(obj, obj, M00_CUSTOM_POWERUP_GRANT_DISABLE, 0);
  176. }
  177. }
  178. };
  179. // DAY - Used to destroy a powerup dropped by the powerup manager over time. Based on Difficulty.
  180. DECLARE_SCRIPT(M00_Powerup_Destroy, "")
  181. {
  182. void Created (GameObject * obj)
  183. {
  184. float lifespan = (30.0f - (Commands->Get_Difficulty_Level() * 10));
  185. Commands->Start_Timer (obj, this, lifespan, 10);
  186. }
  187. void Timer_Expired(GameObject * obj, int timer_id)
  188. {
  189. if(timer_id == 10)
  190. {
  191. Commands->Expire_Powerup(obj);
  192. }
  193. }
  194. };
  195. /***********************************************************************************************
  196. **
  197. ** Reveal Encyclopedia Powerup Scripts. Reveal ID's of encyclopedia ini entries based on type
  198. **
  199. ************************************************************************************************/
  200. // DAY - Reveals a Building entry in the Encyclopedia. Param is the Encyclopedia ID listed in the Buildings.ini file.
  201. DECLARE_SCRIPT (M00_Reveal_Enc_Building_DAY, "BuildingEncyclopediaID:int")
  202. {
  203. void Custom(GameObject *obj, int type, int param, GameObject *sender)
  204. {
  205. if ( type == CUSTOM_EVENT_POWERUP_GRANTED )
  206. {
  207. bool reveal = Commands->Reveal_Encyclopedia_Building( Get_Int_Parameter("BuildingEncyclopediaID") );
  208. if ( reveal == 1 )
  209. {
  210. Commands->Display_Encyclopedia_Event_UI();
  211. }
  212. }
  213. }
  214. };
  215. // DAY - Reveals a Character entry in the Encyclopedia. Param is the Encyclopedia ID listed in the Characters.ini file.
  216. DECLARE_SCRIPT (M00_Reveal_Enc_Character_DAY, "CharacterEncyclopediaID:int")
  217. {
  218. void Custom(GameObject *obj, int type, int param, GameObject *sender)
  219. {
  220. if ( type == CUSTOM_EVENT_POWERUP_GRANTED )
  221. {
  222. bool reveal = Commands->Reveal_Encyclopedia_Character( Get_Int_Parameter("CharacterEncyclopediaID") );
  223. if ( reveal == 1 )
  224. {
  225. Commands->Display_Encyclopedia_Event_UI();
  226. }
  227. }
  228. }
  229. };
  230. // DAY - Reveals a Vehicle entry in the Encyclopedia. Param is the Encyclopedia ID listed in the Vehicles.ini file.
  231. DECLARE_SCRIPT (M00_Reveal_Enc_Vehicle_DAY, "VehicleEncyclopediaID:int")
  232. {
  233. void Custom(GameObject *obj, int type, int param, GameObject *sender)
  234. {
  235. if ( type == CUSTOM_EVENT_POWERUP_GRANTED )
  236. {
  237. bool reveal = Commands->Reveal_Encyclopedia_Vehicle( Get_Int_Parameter("VehicleEncyclopediaID") );
  238. if ( reveal == 1 )
  239. {
  240. Commands->Display_Encyclopedia_Event_UI();
  241. }
  242. }
  243. }
  244. };
  245. // DAY - Reveals a Weapon entry in the Encyclopedia. Param is the Encyclopedia ID listed in the Weapons.ini file.
  246. // Normally not necessary as picking up weapon will reveal entry.
  247. DECLARE_SCRIPT (M00_Reveal_Enc_Weapon_DAY, "WeaponEncyclopediaID:int")
  248. {
  249. void Custom(GameObject *obj, int type, int param, GameObject *sender)
  250. {
  251. if ( type == CUSTOM_EVENT_POWERUP_GRANTED )
  252. {
  253. bool reveal = Commands->Reveal_Encyclopedia_Weapon( Get_Int_Parameter("WeaponEncyclopediaID") );
  254. if ( reveal == 1 )
  255. {
  256. Commands->Display_Encyclopedia_Event_UI();
  257. }
  258. }
  259. }
  260. };
  261. /***********************************************************************************************
  262. **
  263. ** Mutliplayer Score/Money Grant Scripts
  264. ** DAY - Two scripts that grant random incremental allotments of points or money for
  265. ** multiplayer.
  266. **
  267. ************************************************************************************************/
  268. // DAY - Multiplayer Script to Grant Score
  269. DECLARE_SCRIPT (M00_GrantScore_Powerup, "ScoreAmount:float,Entire_Team=0:int,Randomizer=1:int")
  270. {
  271. void Custom( GameObject * obj, int type, int param, GameObject * sender )
  272. {
  273. float score;
  274. bool team_grant;
  275. int random_multiply;
  276. int factor_multiply;
  277. float score_grant;
  278. score = Get_Float_Parameter( "ScoreAmount" );
  279. team_grant = (Get_Int_Parameter("Entire_Team") == 1) ? true : false;
  280. random_multiply = Get_Int_Parameter( "Randomizer" );
  281. if ( random_multiply < 1 )
  282. {
  283. random_multiply = 1;
  284. }
  285. factor_multiply = Commands->Get_Random_Int( 1, (random_multiply + 1) );
  286. score_grant = factor_multiply * score;
  287. if ( type == CUSTOM_EVENT_POWERUP_GRANTED )
  288. {
  289. Commands->Give_Points( sender, score_grant, team_grant );
  290. }
  291. }
  292. };
  293. // DAY - Multiplayer Script to Grant Money
  294. DECLARE_SCRIPT (M00_GrantMoney_Powerup, "ScoreAmount:float,Entire_Team=0:int,Randomizer=1:int")
  295. {
  296. void Custom( GameObject * obj, int type, int param, GameObject * sender )
  297. {
  298. float score;
  299. bool team_grant;
  300. int random_multiply;
  301. int factor_multiply;
  302. float score_grant;
  303. score = Get_Float_Parameter( "ScoreAmount" );
  304. team_grant = (Get_Int_Parameter("Entire_Team") == 1) ? true : false;
  305. random_multiply = Get_Int_Parameter( "Randomizer" );
  306. if ( random_multiply < 1 )
  307. {
  308. random_multiply = 1;
  309. }
  310. factor_multiply = Commands->Get_Random_Int( 1, (random_multiply + 1) );
  311. score_grant = factor_multiply * score;
  312. if ( type == CUSTOM_EVENT_POWERUP_GRANTED )
  313. {
  314. Commands->Give_Money( sender, score_grant, team_grant );
  315. }
  316. }
  317. };
  318. // Attach this script to the Tiberium Refinery controller. It will issue money to that
  319. // controller's team until the Refinery is destroyed.
  320. DECLARE_SCRIPT (M00_Tiberium_Refinery, "MoneyAmount:int,TimerLength:int")
  321. {
  322. void Created (GameObject * obj)
  323. {
  324. Commands->Start_Timer (obj, this, Get_Int_Parameter("TimerLength"), 1);
  325. }
  326. void Timer_Expired (GameObject * obj, int timer_id)
  327. {
  328. if (timer_id == 1)
  329. {
  330. float health = Commands->Get_Health (obj);
  331. if (health)
  332. {
  333. Commands->Give_Money (obj, Get_Int_Parameter ("MoneyAmount"), true);
  334. Commands->Start_Timer (obj, this, Get_Int_Parameter("TimerLength"), 1);
  335. }
  336. }
  337. }
  338. };
  339. DECLARE_SCRIPT (M00_CNC_Crate, "")
  340. {
  341. void Custom (GameObject * obj, int type, int param, GameObject * sender)
  342. {
  343. if ((type == CUSTOM_EVENT_POWERUP_GRANTED) && (sender))
  344. {
  345. Commands->Give_Money (sender, 100.0f, false);
  346. }
  347. }
  348. };
  349. DECLARE_SCRIPT (M00_Death_Powerup, "")
  350. {
  351. void Custom (GameObject * obj, int type, int param, GameObject * sender)
  352. {
  353. if ((type == CUSTOM_EVENT_POWERUP_GRANTED) && (sender))
  354. {
  355. Commands->Apply_Damage (sender, 10000.0f, "Death", NULL);
  356. }
  357. }
  358. };