Guest User

Untitled

a guest
Mar 12th, 2022
40
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 319.90 KB | None | 0 0
  1. /*================================================================================
  2. [Plugin Customization]
  3. =================================================================================*/
  4.  
  5. // All customization settings have been moved
  6. // to external files to allow easier editing
  7. new const ZP_CUSTOMIZATION_FILE[] = "zombieplague.ini"
  8. new const ZP_EXTRAITEMS_FILE[] = "zp_extraitems.ini"
  9. new const ZP_ZOMBIECLASSES_FILE[] = "zp_zombieclasses.ini"
  10.  
  11. // Limiters for stuff not worth making dynamic arrays out of (increase if needed)
  12. const MAX_CSDM_SPAWNS = 128
  13. const MAX_STATS_SAVED = 64
  14.  
  15. /*================================================================================
  16. Customization ends here! Yes, that's it. Editing anything beyond
  17. here is not officially supported. Proceed at your own risk...
  18. =================================================================================*/
  19.  
  20. #include <amxmodx>
  21. #include <amxmisc>
  22. #include <cstrike>
  23. #include <fakemeta>
  24. #include <hamsandwich>
  25. #include <xs>
  26.  
  27. /*================================================================================
  28. [Constants, Offsets, Macros]
  29. =================================================================================*/
  30.  
  31. // Plugin Version
  32. new const PLUGIN_VERSION[] = "4.3"
  33.  
  34. // Customization file sections
  35. enum
  36. {
  37. SECTION_NONE = 0,
  38. SECTION_ACCESS_FLAGS,
  39. SECTION_PLAYER_MODELS,
  40. SECTION_WEAPON_MODELS,
  41. SECTION_GRENADE_SPRITES,
  42. SECTION_SOUNDS,
  43. SECTION_AMBIENCE_SOUNDS,
  44. SECTION_BUY_MENU_WEAPONS,
  45. SECTION_EXTRA_ITEMS_WEAPONS,
  46. SECTION_HARD_CODED_ITEMS_COSTS,
  47. SECTION_WEATHER_EFFECTS,
  48. SECTION_SKY,
  49. SECTION_LIGHTNING,
  50. SECTION_ZOMBIE_DECALS,
  51. SECTION_KNOCKBACK,
  52. SECTION_OBJECTIVE_ENTS,
  53. SECTION_SVC_BAD
  54. }
  55.  
  56. // Access flags
  57. enum
  58. {
  59. ACCESS_ENABLE_MOD = 0,
  60. ACCESS_ADMIN_MENU,
  61. ACCESS_MODE_INFECTION,
  62. ACCESS_MODE_NEMESIS,
  63. ACCESS_MODE_SURVIVOR,
  64. ACCESS_MODE_SWARM,
  65. ACCESS_MODE_MULTI,
  66. ACCESS_MODE_PLAGUE,
  67. ACCESS_MAKE_ZOMBIE,
  68. ACCESS_MAKE_HUMAN,
  69. ACCESS_MAKE_NEMESIS,
  70. ACCESS_MAKE_SURVIVOR,
  71. ACCESS_RESPAWN_PLAYERS,
  72. ACCESS_ADMIN_MODELS,
  73. MAX_ACCESS_FLAGS
  74. }
  75.  
  76. // Task offsets
  77. enum (+= 100)
  78. {
  79. TASK_MODEL = 2000,
  80. TASK_TEAM,
  81. TASK_SPAWN,
  82. TASK_BLOOD,
  83. TASK_AURA,
  84. TASK_BURN,
  85. TASK_NVISION,
  86. TASK_FLASH,
  87. TASK_CHARGE,
  88. TASK_SHOWHUD,
  89. TASK_MAKEZOMBIE,
  90. TASK_WELCOMEMSG,
  91. TASK_THUNDER_PRE,
  92. TASK_THUNDER,
  93. TASK_AMBIENCESOUNDS
  94. }
  95.  
  96. // IDs inside tasks
  97. #define ID_MODEL (taskid - TASK_MODEL)
  98. #define ID_TEAM (taskid - TASK_TEAM)
  99. #define ID_SPAWN (taskid - TASK_SPAWN)
  100. #define ID_BLOOD (taskid - TASK_BLOOD)
  101. #define ID_AURA (taskid - TASK_AURA)
  102. #define ID_BURN (taskid - TASK_BURN)
  103. #define ID_NVISION (taskid - TASK_NVISION)
  104. #define ID_FLASH (taskid - TASK_FLASH)
  105. #define ID_CHARGE (taskid - TASK_CHARGE)
  106. #define ID_SHOWHUD (taskid - TASK_SHOWHUD)
  107.  
  108. // BP Ammo Refill task
  109. #define REFILL_WEAPONID args[0]
  110.  
  111. // For weapon buy menu handlers
  112. #define WPN_STARTID g_menu_data[id][1]
  113. #define WPN_MAXIDS ArraySize(g_primary_items)
  114. #define WPN_SELECTION (g_menu_data[id][1]+key)
  115. #define WPN_AUTO_ON g_menu_data[id][2]
  116. #define WPN_AUTO_PRI g_menu_data[id][3]
  117. #define WPN_AUTO_SEC g_menu_data[id][4]
  118.  
  119. // For player list menu handlers
  120. #define PL_ACTION g_menu_data[id][0]
  121.  
  122. // For extra items menu handlers
  123. #define EXTRAS_CUSTOM_STARTID (EXTRA_WEAPONS_STARTID + ArraySize(g_extraweapon_names))
  124.  
  125. // Menu selections
  126. const MENU_KEY_AUTOSELECT = 7
  127. const MENU_KEY_BACK = 7
  128. const MENU_KEY_NEXT = 8
  129. const MENU_KEY_EXIT = 9
  130.  
  131. // Hard coded extra items
  132. enum
  133. {
  134. EXTRA_NVISION = 0,
  135. EXTRA_ANTIDOTE,
  136. EXTRA_MADNESS,
  137. EXTRA_INFBOMB,
  138. EXTRA_WEAPONS_STARTID
  139. }
  140.  
  141. // Game modes
  142. enum
  143. {
  144. MODE_NONE = 0,
  145. MODE_INFECTION,
  146. MODE_NEMESIS,
  147. MODE_SURVIVOR,
  148. MODE_SWARM,
  149. MODE_MULTI,
  150. MODE_PLAGUE
  151. }
  152.  
  153. // ZP Teams
  154. const ZP_TEAM_NO_ONE = 0
  155. const ZP_TEAM_ANY = 0
  156. const ZP_TEAM_ZOMBIE = (1<<0)
  157. const ZP_TEAM_HUMAN = (1<<1)
  158. const ZP_TEAM_NEMESIS = (1<<2)
  159. const ZP_TEAM_SURVIVOR = (1<<3)
  160. new const ZP_TEAM_NAMES[][] = { "ZOMBIE , HUMAN", "ZOMBIE", "HUMAN", "ZOMBIE , HUMAN", "NEMESIS",
  161. "ZOMBIE , NEMESIS", "HUMAN , NEMESIS", "ZOMBIE , HUMAN , NEMESIS",
  162. "SURVIVOR", "ZOMBIE , SURVIVOR", "HUMAN , SURVIVOR", "ZOMBIE , HUMAN , SURVIVOR",
  163. "NEMESIS , SURVIVOR", "ZOMBIE , NEMESIS , SURVIVOR", "HUMAN, NEMESIS, SURVIVOR",
  164. "ZOMBIE , HUMAN , NEMESIS , SURVIVOR" }
  165.  
  166. // Zombie classes
  167. const ZCLASS_NONE = -1
  168.  
  169. // HUD messages
  170. const Float:HUD_EVENT_X = -1.0
  171. const Float:HUD_EVENT_Y = 0.17
  172. const Float:HUD_INFECT_X = 0.05
  173. const Float:HUD_INFECT_Y = 0.45
  174. const Float:HUD_SPECT_X = 0.6
  175. const Float:HUD_SPECT_Y = 0.8
  176. const Float:HUD_STATS_X = 0.01
  177. const Float:HUD_STATS_Y = 0.28
  178.  
  179. // CS Player PData Offsets (win32)
  180. const OFFSET_PAINSHOCK = 108 // ConnorMcLeod
  181. const OFFSET_CSTEAMS = 114
  182. const OFFSET_CSMONEY = 115
  183. const OFFSET_FLASHLIGHT_BATTERY = 244
  184. const OFFSET_CSDEATHS = 444
  185. const OFFSET_MODELINDEX = 491 // Orangutanz
  186.  
  187. // CS Player CBase Offsets (win32)
  188. const OFFSET_ACTIVE_ITEM = 373
  189.  
  190. // CS Weapon CBase Offsets (win32)
  191. const OFFSET_WEAPONOWNER = 41
  192.  
  193. // Linux diff's
  194. const OFFSET_LINUX = 5 // offsets 5 higher in Linux builds
  195. const OFFSET_LINUX_WEAPONS = 4 // weapon offsets are only 4 steps higher on Linux
  196.  
  197. // CS Teams
  198. enum
  199. {
  200. FM_CS_TEAM_UNASSIGNED = 0,
  201. FM_CS_TEAM_T,
  202. FM_CS_TEAM_CT,
  203. FM_CS_TEAM_SPECTATOR
  204. }
  205. new const CS_TEAM_NAMES[][] = { "UNASSIGNED", "TERRORIST", "CT", "SPECTATOR" }
  206.  
  207. // Some constants
  208. const HIDE_MONEY = (1<<5)
  209. const UNIT_SECOND = (1<<12)
  210. const DMG_HEGRENADE = (1<<24)
  211. const IMPULSE_FLASHLIGHT = 100
  212. const USE_USING = 2
  213. const USE_STOPPED = 0
  214. const STEPTIME_SILENT = 999
  215. const BREAK_GLASS = 0x01
  216. const FFADE_IN = 0x0000
  217. const FFADE_STAYOUT = 0x0004
  218. const PEV_SPEC_TARGET = pev_iuser2
  219.  
  220. // Max BP ammo for weapons
  221. new const MAXBPAMMO[] = { -1, 52, -1, 90, 1, 32, 1, 100, 90, 1, 120, 100, 100, 90, 90, 90, 100, 120,
  222. 30, 120, 200, 32, 90, 120, 90, 2, 35, 90, 90, -1, 100 }
  223.  
  224. // Max Clip for weapons
  225. new const MAXCLIP[] = { -1, 13, -1, 10, -1, 7, -1, 30, 30, -1, 30, 20, 25, 30, 35, 25, 12, 20,
  226. 10, 30, 100, 8, 30, 30, 20, -1, 7, 30, 30, -1, 50 }
  227.  
  228. // Amount of ammo to give when buying additional clips for weapons
  229. new const BUYAMMO[] = { -1, 13, -1, 30, -1, 8, -1, 12, 30, -1, 30, 50, 12, 30, 30, 30, 12, 30,
  230. 10, 30, 30, 8, 30, 30, 30, -1, 7, 30, 30, -1, 50 }
  231.  
  232. // Ammo IDs for weapons
  233. new const AMMOID[] = { -1, 9, -1, 2, 12, 5, 14, 6, 4, 13, 10, 7, 6, 4, 4, 4, 6, 10,
  234. 1, 10, 3, 5, 4, 10, 2, 11, 8, 4, 2, -1, 7 }
  235.  
  236. // Ammo Type Names for weapons
  237. new const AMMOTYPE[][] = { "", "357sig", "", "762nato", "", "buckshot", "", "45acp", "556nato", "", "9mm", "57mm", "45acp",
  238. "556nato", "556nato", "556nato", "45acp", "9mm", "338magnum", "9mm", "556natobox", "buckshot",
  239. "556nato", "9mm", "762nato", "", "50ae", "556nato", "762nato", "", "57mm" }
  240.  
  241. // Weapon IDs for ammo types
  242. new const AMMOWEAPON[] = { 0, CSW_AWP, CSW_SCOUT, CSW_M249, CSW_AUG, CSW_XM1014, CSW_MAC10, CSW_FIVESEVEN, CSW_DEAGLE,
  243. CSW_P228, CSW_ELITE, CSW_FLASHBANG, CSW_HEGRENADE, CSW_SMOKEGRENADE, CSW_C4 }
  244.  
  245. // Primary and Secondary Weapon Names
  246. new const WEAPONNAMES[][] = { "", "P228 Compact", "", "Schmidt Scout", "", "XM1014 M4", "", "Ingram MAC-10", "Steyr AUG A1",
  247. "", "Dual Elite Berettas", "FiveseveN", "UMP 45", "SG-550 Auto-Sniper", "IMI Galil", "Famas",
  248. "USP .45 ACP Tactical", "Glock 18C", "AWP Magnum Sniper", "MP5 Navy", "M249 Para Machinegun",
  249. "M3 Super 90", "M4A1 Carbine", "Schmidt TMP", "G3SG1 Auto-Sniper", "", "Desert Eagle .50 AE",
  250. "SG-552 Commando", "AK-47 Kalashnikov", "", "ES P90" }
  251.  
  252. // Weapon entity names
  253. new const WEAPONENTNAMES[][] = { "", "weapon_p228", "", "weapon_scout", "weapon_hegrenade", "weapon_xm1014", "weapon_c4", "weapon_mac10",
  254. "weapon_aug", "weapon_smokegrenade", "weapon_elite", "weapon_fiveseven", "weapon_ump45", "weapon_sg550",
  255. "weapon_galil", "weapon_famas", "weapon_usp", "weapon_glock18", "weapon_awp", "weapon_mp5navy", "weapon_m249",
  256. "weapon_m3", "weapon_m4a1", "weapon_tmp", "weapon_g3sg1", "weapon_flashbang", "weapon_deagle", "weapon_sg552",
  257. "weapon_ak47", "weapon_knife", "weapon_p90" }
  258.  
  259. // CS sounds
  260. new const sound_flashlight[] = "items/flashlight1.wav"
  261. new const sound_buyammo[] = "items/9mmclip1.wav"
  262. new const sound_armorhit[] = "player/bhit_helmet-1.wav"
  263.  
  264. // Explosion radius for custom grenades
  265. const Float:NADE_EXPLOSION_RADIUS = 240.0
  266.  
  267. // HACK: pev_ field used to store additional ammo on weapons
  268. const PEV_ADDITIONAL_AMMO = pev_iuser1
  269.  
  270. // HACK: pev_ field used to store custom nade types and their values
  271. const PEV_NADE_TYPE = pev_flTimeStepSound
  272. const NADE_TYPE_INFECTION = 1111
  273. const NADE_TYPE_NAPALM = 2222
  274. const NADE_TYPE_FROST = 3333
  275. const NADE_TYPE_FLARE = 4444
  276. const PEV_FLARE_COLOR = pev_punchangle
  277. const PEV_FLARE_DURATION = pev_flSwimTime
  278.  
  279. // Weapon bitsums
  280. const PRIMARY_WEAPONS_BIT_SUM = (1<<CSW_SCOUT)|(1<<CSW_XM1014)|(1<<CSW_MAC10)|(1<<CSW_AUG)|(1<<CSW_UMP45)|(1<<CSW_SG550)|(1<<CSW_GALIL)|(1<<CSW_FAMAS)|(1<<CSW_AWP)|(1<<CSW_MP5NAVY)|(1<<CSW_M249)|(1<<CSW_M3)|(1<<CSW_M4A1)|(1<<CSW_TMP)|(1<<CSW_G3SG1)|(1<<CSW_SG552)|(1<<CSW_AK47)|(1<<CSW_P90)
  281. const SECONDARY_WEAPONS_BIT_SUM = (1<<CSW_P228)|(1<<CSW_ELITE)|(1<<CSW_FIVESEVEN)|(1<<CSW_USP)|(1<<CSW_GLOCK18)|(1<<CSW_DEAGLE)
  282.  
  283. // Allowed weapons for zombies (added grenades/bomb for sub-plugin support, since they shouldn't be getting them anyway)
  284. const ZOMBIE_ALLOWED_WEAPONS_BITSUM = (1<<CSW_KNIFE)|(1<<CSW_HEGRENADE)|(1<<CSW_FLASHBANG)|(1<<CSW_SMOKEGRENADE)|(1<<CSW_C4)
  285.  
  286. // Classnames for separate model entities
  287. new const MODEL_ENT_CLASSNAME[] = "player_model"
  288. new const WEAPON_ENT_CLASSNAME[] = "weapon_model"
  289.  
  290. // Menu keys
  291. const KEYSMENU = MENU_KEY_1|MENU_KEY_2|MENU_KEY_3|MENU_KEY_4|MENU_KEY_5|MENU_KEY_6|MENU_KEY_7|MENU_KEY_8|MENU_KEY_9|MENU_KEY_0
  292.  
  293. // Ambience Sounds
  294. enum
  295. {
  296. AMBIENCE_SOUNDS_INFECTION = 0,
  297. AMBIENCE_SOUNDS_NEMESIS,
  298. AMBIENCE_SOUNDS_SURVIVOR,
  299. AMBIENCE_SOUNDS_SWARM,
  300. AMBIENCE_SOUNDS_PLAGUE,
  301. MAX_AMBIENCE_SOUNDS
  302. }
  303.  
  304. // Admin menu actions
  305. enum
  306. {
  307. ACTION_ZOMBIEFY_HUMANIZE = 0,
  308. ACTION_MAKE_NEMESIS,
  309. ACTION_MAKE_SURVIVOR,
  310. ACTION_RESPAWN_PLAYER,
  311. ACTION_MODE_SWARM,
  312. ACTION_MODE_MULTI,
  313. ACTION_MODE_PLAGUE
  314. }
  315.  
  316. // Custom forward return values
  317. const ZP_PLUGIN_HANDLED = 97
  318.  
  319. /*================================================================================
  320. [Global Variables]
  321. =================================================================================*/
  322.  
  323. // Player vars
  324. new g_zombie[33] // is zombie
  325. new g_nemesis[33] // is nemesis
  326. new g_survivor[33] // is survivor
  327. new g_firstzombie[33] // is first zombie
  328. new g_lastzombie[33] // is last zombie
  329. new g_lasthuman[33] // is last human
  330. new g_frozen[33] // is frozen (can't move)
  331. new g_nodamage[33] // has spawn protection/zombie madness
  332. new g_respawn_as_zombie[33] // should respawn as zombie
  333. new g_nvision[33] // has night vision
  334. new g_nvisionenabled[33] // has night vision turned on
  335. new g_zombieclass[33] // zombie class
  336. new g_zombieclassnext[33] // zombie class for next infection
  337. new g_flashlight[33] // has custom flashlight turned on
  338. new g_flashbattery[33] = { 100, ... } // custom flashlight battery
  339. new g_canbuy[33] // is allowed to buy a new weapon through the menu
  340. new g_ammopacks[33] // ammo pack count
  341. new g_damagedealt[33] // damage dealt to zombies (used to calculate ammo packs reward)
  342. new Float:g_lastleaptime[33] // time leap was last used
  343. new Float:g_lastflashtime[33] // time flashlight was last toggled
  344. new g_playermodel[33][32] // current model's short name [player][model]
  345. new g_menu_data[33][5] // data for some menu handlers
  346. new g_ent_playermodel[33] // player model entity
  347. new g_ent_weaponmodel[33] // weapon model entity
  348. new g_burning_duration[33] // burning task duration
  349.  
  350. // Game vars
  351. new g_pluginenabled // ZP enabled
  352. new g_newround // new round starting
  353. new g_endround // round ended
  354. new g_nemround // nemesis round
  355. new g_survround // survivor round
  356. new g_swarmround // swarm round
  357. new g_plagueround // plague round
  358. new g_modestarted // mode fully started
  359. new g_lastmode // last played mode
  360. new g_scorezombies, g_scorehumans // team scores
  361. new g_spawnCount, g_spawnCount2 // available spawn points counter
  362. new Float:g_spawns[MAX_CSDM_SPAWNS][3], Float:g_spawns2[MAX_CSDM_SPAWNS][3] // spawn points data
  363. new g_lights_i // lightning current lights counter
  364. new g_lights_cycle[32] // current lightning cycle
  365. new g_lights_cycle_len // lightning cycle length
  366. new Float:g_models_targettime // for adding delays between Model Change messages
  367. new Float:g_teams_targettime // for adding delays between Team Change messages
  368. new g_MsgSync, g_MsgSync2 // message sync objects
  369. new g_trailSpr, g_exploSpr, g_flameSpr, g_smokeSpr, g_glassSpr // grenade sprites
  370. new g_modname[32] // for formatting the mod name
  371. new g_freezetime // whether CS's freeze time is on
  372. new g_maxplayers // max players counter
  373. new g_czero // whether we are running on a CZ server
  374. new g_hamczbots // whether ham forwards are registered for CZ bots
  375. new g_fwSpawn, g_fwPrecacheSound // spawn and precache sound forward handles
  376. new g_infbombcounter, g_antidotecounter, g_madnesscounter // to limit buying some items
  377. new g_arrays_created // to prevent stuff from being registered before initializing arrays
  378. new g_lastplayerleaving // flag for whenever a player leaves and another takes his place
  379. new g_switchingteam // flag for whenever a player's team change emessage is sent
  380.  
  381. // Message IDs vars
  382. new g_msgScoreInfo, g_msgNVGToggle, g_msgScoreAttrib, g_msgAmmoPickup, g_msgScreenFade,
  383. g_msgDeathMsg, g_msgSetFOV, g_msgFlashlight, g_msgFlashBat, g_msgTeamInfo, g_msgDamage,
  384. g_msgHideWeapon, g_msgCrosshair, g_msgSayText, g_msgScreenShake, g_msgCurWeapon
  385.  
  386. // Some forward handlers
  387. new g_fwRoundStart, g_fwRoundEnd, g_fwUserInfected_pre, g_fwUserInfected_post,
  388. g_fwUserHumanized_pre, g_fwUserHumanized_post, g_fwUserInfect_attempt,
  389. g_fwUserHumanize_attempt, g_fwExtraItemSelected, g_fwUserUnfrozen,
  390. g_fwUserLastZombie, g_fwUserLastHuman, g_fwDummyResult
  391.  
  392. // Temporary Database vars (used to restore players stats in case they get disconnected)
  393. new db_name[MAX_STATS_SAVED][32] // player name
  394. new db_ammopacks[MAX_STATS_SAVED] // ammo pack count
  395. new db_zombieclass[MAX_STATS_SAVED] // zombie class
  396. new db_slot_i // additional saved slots counter (should start on maxplayers+1)
  397.  
  398. // Extra Items vars
  399. new Array:g_extraitem_name // caption
  400. new Array:g_extraitem_cost // cost
  401. new Array:g_extraitem_team // team
  402. new g_extraitem_i // loaded extra items counter
  403.  
  404. // For extra items file parsing
  405. new Array:g_extraitem2_realname, Array:g_extraitem2_name, Array:g_extraitem2_cost,
  406. Array:g_extraitem2_team, Array:g_extraitem_new
  407.  
  408. // Zombie Classes vars
  409. new Array:g_zclass_name // caption
  410. new Array:g_zclass_info // description
  411. new Array:g_zclass_modelsstart // start position in models array
  412. new Array:g_zclass_modelsend // end position in models array
  413. new Array:g_zclass_playermodel // player models array
  414. new Array:g_zclass_modelindex // model indices array
  415. new Array:g_zclass_clawmodel // claw model
  416. new Array:g_zclass_hp // health
  417. new Array:g_zclass_spd // speed
  418. new Array:g_zclass_grav // gravity
  419. new Array:g_zclass_kb // knockback
  420. new g_zclass_i // loaded zombie classes counter
  421.  
  422. // For zombie classes file parsing
  423. new Array:g_zclass2_realname, Array:g_zclass2_name, Array:g_zclass2_info,
  424. Array:g_zclass2_modelsstart, Array:g_zclass2_modelsend, Array:g_zclass2_playermodel,
  425. Array:g_zclass2_modelindex, Array:g_zclass2_clawmodel, Array:g_zclass2_hp,
  426. Array:g_zclass2_spd, Array:g_zclass2_grav, Array:g_zclass2_kb, Array:g_zclass_new
  427.  
  428. // Customization vars
  429. new g_access_flag[MAX_ACCESS_FLAGS], Array:model_nemesis, Array:model_survivor, Array:model_human,
  430. Array:model_admin_zombie, Array:model_admin_human, Array:g_modelindex_human,
  431. Array:g_modelindex_nemesis, Array:g_modelindex_survivor, g_same_models_for_all,
  432. Array:g_modelindex_admin_zombie, Array:g_modelindex_admin_human, model_vknife_human[64],
  433. model_vknife_nemesis[64], model_vm249_survivor[64], model_grenade_infect[64],
  434. model_grenade_fire[64], model_grenade_frost[64], model_grenade_flare[64],
  435. model_vknife_admin_human[64], model_vknife_admin_zombie[64],
  436. sprite_grenade_trail[64], sprite_grenade_ring[64], sprite_grenade_fire[64],
  437. sprite_grenade_smoke[64], sprite_grenade_glass[64], Array:sound_win_zombies,
  438. Array:sound_win_humans, Array:sound_win_no_one, Array:zombie_infect, Array:zombie_idle,
  439. Array:zombie_pain, Array:nemesis_pain, Array:zombie_die, Array:zombie_fall,
  440. Array:zombie_miss_wall, Array:zombie_hit_normal, Array:zombie_hit_stab, g_ambience_rain,
  441. Array:zombie_idle_last, Array:zombie_madness, Array:sound_nemesis, Array:sound_survivor,
  442. Array:sound_swarm, Array:sound_multi, Array:sound_plague, Array:grenade_infect,
  443. Array:grenade_infect_player, Array:grenade_fire, Array:grenade_fire_player,
  444. Array:grenade_frost, Array:grenade_frost_player, Array:grenade_frost_break,
  445. Array:grenade_flare, Array:sound_antidote, Array:sound_thunder, g_ambience_sounds[MAX_AMBIENCE_SOUNDS],
  446. Array:sound_ambience1, Array:sound_ambience2, Array:sound_ambience3, Array:sound_ambience4,
  447. Array:sound_ambience5, Array:sound_ambience1_duration, Array:sound_ambience2_duration,
  448. Array:sound_ambience3_duration, Array:sound_ambience4_duration,
  449. Array:sound_ambience5_duration, Array:sound_ambience1_ismp3, Array:sound_ambience2_ismp3,
  450. Array:sound_ambience3_ismp3, Array:sound_ambience4_ismp3, Array:sound_ambience5_ismp3,
  451. Array:g_primary_items, Array:g_secondary_items, Array:g_additional_items,
  452. Array:g_primary_weaponids, Array:g_secondary_weaponids, Array:g_extraweapon_names,
  453. Array:g_extraweapon_items, Array:g_extraweapon_costs, g_extra_costs2[EXTRA_WEAPONS_STARTID],
  454. g_ambience_snow, g_ambience_fog, g_fog_density[10], g_fog_color[12], g_sky_enable,
  455. Array:g_sky_names, Array:lights_thunder, Array:zombie_decals, Array:g_objective_ents,
  456. Float:g_modelchange_delay, g_set_modelindex_offset, g_handle_models_on_separate_ent,
  457. Float:kb_weapon_power[31] = { -1.0, ... }, Array:zombie_miss_slash, g_force_consistency
  458.  
  459. // CVAR pointers
  460. new cvar_lighting, cvar_zombiefov, cvar_plague, cvar_plaguechance, cvar_zombiefirsthp,
  461. cvar_removemoney, cvar_thunder, cvar_zombiebonushp, cvar_nemhp, cvar_nem, cvar_surv,
  462. cvar_nemchance, cvar_deathmatch, cvar_nemglow, cvar_customnvg, cvar_hitzones, cvar_humanhp,
  463. cvar_nemgravity, cvar_flashsize, cvar_ammodamage, cvar_zombiearmor, cvar_survpainfree,
  464. cvar_nempainfree, cvar_nemspd, cvar_survchance, cvar_survhp, cvar_survspd, cvar_humanspd,
  465. cvar_swarmchance, cvar_flashdrain, cvar_zombiebleeding, cvar_removedoors, cvar_customflash,
  466. cvar_randspawn, cvar_multi, cvar_multichance, cvar_infammo, cvar_swarm, cvar_ammoinfect,
  467. cvar_toggle, cvar_knockbackpower, cvar_freezeduration, cvar_triggered, cvar_flashcharge,
  468. cvar_firegrenades, cvar_frostgrenades, cvar_survgravity, cvar_logcommands, cvar_survglow,
  469. cvar_humangravity, cvar_spawnprotection, cvar_nvgsize, cvar_flareduration, cvar_zclasses,
  470. cvar_extraitems, cvar_showactivity, cvar_humanlasthp, cvar_nemignorefrags, cvar_warmup,
  471. cvar_flashdist, cvar_flarecolor, cvar_survignorefrags, cvar_fireduration, cvar_firedamage,
  472. cvar_flaregrenades, cvar_knockbackducking, cvar_knockbackdamage, cvar_knockbackzvel,
  473. cvar_multiratio, cvar_flaresize, cvar_spawndelay, cvar_extraantidote, cvar_extramadness,
  474. cvar_extraweapons, cvar_extranvision, cvar_nvggive, cvar_preventconsecutive, cvar_botquota,
  475. cvar_buycustom, cvar_zombiepainfree, cvar_fireslowdown, cvar_survbasehp, cvar_survaura,
  476. cvar_nemignoreammo, cvar_survignoreammo, cvar_nemaura, cvar_extrainfbomb, cvar_knockback,
  477. cvar_fragsinfect, cvar_fragskill, cvar_humanarmor, cvar_zombiesilent, cvar_removedropped,
  478. cvar_plagueratio, cvar_blocksuicide, cvar_knockbackdist, cvar_nemdamage, cvar_leapzombies,
  479. cvar_leapzombiesforce, cvar_leapzombiesheight, cvar_leapzombiescooldown, cvar_leapnemesis,
  480. cvar_leapnemesisforce, cvar_leapnemesisheight, cvar_leapnemesiscooldown, cvar_leapsurvivor,
  481. cvar_leapsurvivorforce, cvar_leapsurvivorheight, cvar_nemminplayers, cvar_survminplayers,
  482. cvar_respawnonsuicide, cvar_respawnafterlast, cvar_leapsurvivorcooldown, cvar_statssave,
  483. cvar_swarmminplayers, cvar_multiminplayers, cvar_plagueminplayers, cvar_adminmodelshuman,
  484. cvar_adminmodelszombie, cvar_nembasehp, cvar_blockpushables, cvar_respawnworldspawnkill,
  485. cvar_madnessduration, cvar_plaguenemnum, cvar_plaguenemhpmulti, cvar_plaguesurvhpmulti,
  486. cvar_survweapon, cvar_plaguesurvnum, cvar_infectionscreenfade, cvar_infectionscreenshake,
  487. cvar_infectionsparkle, cvar_infectiontracers, cvar_infectionparticles, cvar_infbomblimit,
  488. cvar_allowrespawnsurv, cvar_flashshowall, cvar_allowrespawninfection, cvar_allowrespawnnem,
  489. cvar_allowrespawnswarm, cvar_allowrespawnplague, cvar_survinfammo, cvar_nemknockback,
  490. cvar_nvgcolor[3], cvar_nemnvgcolor[3], cvar_humnvgcolor[3], cvar_flashcolor[3],
  491. cvar_hudicons, cvar_respawnzomb, cvar_respawnhum, cvar_respawnnem, cvar_respawnsurv,
  492. cvar_startammopacks, cvar_randweapons, cvar_antidotelimit, cvar_madnesslimit,
  493. cvar_adminknifemodelshuman, cvar_adminknifemodelszombie, cvar_keephealthondisconnect
  494.  
  495. // Cached stuff for players
  496. new g_isconnected[33] // whether player is connected
  497. new g_isalive[33] // whether player is alive
  498. new g_isbot[33] // whether player is a bot
  499. new g_currentweapon[33] // player's current weapon id
  500. new g_playername[33][32] // player's name
  501. new Float:g_zombie_spd[33] // zombie class speed
  502. new Float:g_zombie_knockback[33] // zombie class knockback
  503. new g_zombie_classname[33][32] // zombie class name
  504. #define is_user_valid_connected(%1) (1 <= %1 <= g_maxplayers && g_isconnected[%1])
  505. #define is_user_valid_alive(%1) (1 <= %1 <= g_maxplayers && g_isalive[%1])
  506.  
  507. // Cached CVARs
  508. new g_cached_customflash, g_cached_zombiesilent, Float:g_cached_humanspd, Float:g_cached_nemspd,
  509. Float:g_cached_survspd, g_cached_leapzombies, Float:g_cached_leapzombiescooldown, g_cached_leapnemesis,
  510. Float:g_cached_leapnemesiscooldown, g_cached_leapsurvivor, Float:g_cached_leapsurvivorcooldown
  511.  
  512. /*================================================================================
  513. [Natives, Precache and Init]
  514. =================================================================================*/
  515.  
  516. public plugin_natives()
  517. {
  518. // Player specific natives
  519. register_native("zp_get_user_zombie", "native_get_user_zombie", 1)
  520. register_native("zp_get_user_nemesis", "native_get_user_nemesis", 1)
  521. register_native("zp_get_user_survivor", "native_get_user_survivor", 1)
  522. register_native("zp_get_user_first_zombie", "native_get_user_first_zombie", 1)
  523. register_native("zp_get_user_last_zombie", "native_get_user_last_zombie", 1)
  524. register_native("zp_get_user_last_human", "native_get_user_last_human", 1)
  525. register_native("zp_get_user_zombie_class", "native_get_user_zombie_class", 1)
  526. register_native("zp_get_user_next_class", "native_get_user_next_class", 1)
  527. register_native("zp_set_user_zombie_class", "native_set_user_zombie_class", 1)
  528. register_native("zp_get_user_ammo_packs", "native_get_user_ammo_packs", 1)
  529. register_native("zp_set_user_ammo_packs", "native_set_user_ammo_packs", 1)
  530. register_native("zp_get_zombie_maxhealth", "native_get_zombie_maxhealth", 1)
  531. register_native("zp_get_user_batteries", "native_get_user_batteries", 1)
  532. register_native("zp_set_user_batteries", "native_set_user_batteries", 1)
  533. register_native("zp_get_user_nightvision", "native_get_user_nightvision", 1)
  534. register_native("zp_set_user_nightvision", "native_set_user_nightvision", 1)
  535. register_native("zp_infect_user", "native_infect_user", 1)
  536. register_native("zp_disinfect_user", "native_disinfect_user", 1)
  537. register_native("zp_make_user_nemesis", "native_make_user_nemesis", 1)
  538. register_native("zp_make_user_survivor", "native_make_user_survivor", 1)
  539. register_native("zp_respawn_user", "native_respawn_user", 1)
  540. register_native("zp_force_buy_extra_item", "native_force_buy_extra_item", 1)
  541.  
  542. // Round natives
  543. register_native("zp_has_round_started", "native_has_round_started", 1)
  544. register_native("zp_is_nemesis_round", "native_is_nemesis_round", 1)
  545. register_native("zp_is_survivor_round", "native_is_survivor_round", 1)
  546. register_native("zp_is_swarm_round", "native_is_swarm_round", 1)
  547. register_native("zp_is_plague_round", "native_is_plague_round", 1)
  548. register_native("zp_get_zombie_count", "native_get_zombie_count", 1)
  549. register_native("zp_get_human_count", "native_get_human_count", 1)
  550. register_native("zp_get_nemesis_count", "native_get_nemesis_count", 1)
  551. register_native("zp_get_survivor_count", "native_get_survivor_count", 1)
  552.  
  553. // External additions natives
  554. register_native("zp_register_extra_item", "native_register_extra_item", 1)
  555. register_native("zp_register_zombie_class", "native_register_zombie_class", 1)
  556. register_native("zp_get_extra_item_id", "native_get_extra_item_id", 1)
  557. register_native("zp_get_zombie_class_id", "native_get_zombie_class_id", 1)
  558. }
  559.  
  560. public plugin_precache()
  561. {
  562. // Register earlier to show up in plugins list properly after plugin disable/error at loading
  563. register_plugin("Zombie Plague", PLUGIN_VERSION, "MeRcyLeZZ")
  564.  
  565. // To switch plugin on/off
  566. register_concmd("zp_toggle", "cmd_toggle", _, "<1/0> - Enable/Disable Zombie Plague (will restart the current map)", 0)
  567. cvar_toggle = register_cvar("zp_on", "1")
  568.  
  569. // Plugin disabled?
  570. if (!get_pcvar_num(cvar_toggle)) return;
  571. g_pluginenabled = true
  572.  
  573. // Initialize a few dynamically sized arrays (alright, maybe more than just a few...)
  574. model_human = ArrayCreate(32, 1)
  575. model_nemesis = ArrayCreate(32, 1)
  576. model_survivor = ArrayCreate(32, 1)
  577. model_admin_human = ArrayCreate(32, 1)
  578. model_admin_zombie = ArrayCreate(32, 1)
  579. g_modelindex_human = ArrayCreate(1, 1)
  580. g_modelindex_nemesis = ArrayCreate(1, 1)
  581. g_modelindex_survivor = ArrayCreate(1, 1)
  582. g_modelindex_admin_human = ArrayCreate(1, 1)
  583. g_modelindex_admin_zombie = ArrayCreate(1, 1)
  584. sound_win_zombies = ArrayCreate(64, 1)
  585. sound_win_humans = ArrayCreate(64, 1)
  586. sound_win_no_one = ArrayCreate(64, 1)
  587. zombie_infect = ArrayCreate(64, 1)
  588. zombie_pain = ArrayCreate(64, 1)
  589. nemesis_pain = ArrayCreate(64, 1)
  590. zombie_die = ArrayCreate(64, 1)
  591. zombie_fall = ArrayCreate(64, 1)
  592. zombie_miss_slash = ArrayCreate(64, 1)
  593. zombie_miss_wall = ArrayCreate(64, 1)
  594. zombie_hit_normal = ArrayCreate(64, 1)
  595. zombie_hit_stab = ArrayCreate(64, 1)
  596. zombie_idle = ArrayCreate(64, 1)
  597. zombie_idle_last = ArrayCreate(64, 1)
  598. zombie_madness = ArrayCreate(64, 1)
  599. sound_nemesis = ArrayCreate(64, 1)
  600. sound_survivor = ArrayCreate(64, 1)
  601. sound_swarm = ArrayCreate(64, 1)
  602. sound_multi = ArrayCreate(64, 1)
  603. sound_plague = ArrayCreate(64, 1)
  604. grenade_infect = ArrayCreate(64, 1)
  605. grenade_infect_player = ArrayCreate(64, 1)
  606. grenade_fire = ArrayCreate(64, 1)
  607. grenade_fire_player = ArrayCreate(64, 1)
  608. grenade_frost = ArrayCreate(64, 1)
  609. grenade_frost_player = ArrayCreate(64, 1)
  610. grenade_frost_break = ArrayCreate(64, 1)
  611. grenade_flare = ArrayCreate(64, 1)
  612. sound_antidote = ArrayCreate(64, 1)
  613. sound_thunder = ArrayCreate(64, 1)
  614. sound_ambience1 = ArrayCreate(64, 1)
  615. sound_ambience2 = ArrayCreate(64, 1)
  616. sound_ambience3 = ArrayCreate(64, 1)
  617. sound_ambience4 = ArrayCreate(64, 1)
  618. sound_ambience5 = ArrayCreate(64, 1)
  619. sound_ambience1_duration = ArrayCreate(1, 1)
  620. sound_ambience2_duration = ArrayCreate(1, 1)
  621. sound_ambience3_duration = ArrayCreate(1, 1)
  622. sound_ambience4_duration = ArrayCreate(1, 1)
  623. sound_ambience5_duration = ArrayCreate(1, 1)
  624. sound_ambience1_ismp3 = ArrayCreate(1, 1)
  625. sound_ambience2_ismp3 = ArrayCreate(1, 1)
  626. sound_ambience3_ismp3 = ArrayCreate(1, 1)
  627. sound_ambience4_ismp3 = ArrayCreate(1, 1)
  628. sound_ambience5_ismp3 = ArrayCreate(1, 1)
  629. g_primary_items = ArrayCreate(32, 1)
  630. g_secondary_items = ArrayCreate(32, 1)
  631. g_additional_items = ArrayCreate(32, 1)
  632. g_primary_weaponids = ArrayCreate(1, 1)
  633. g_secondary_weaponids = ArrayCreate(1, 1)
  634. g_extraweapon_names = ArrayCreate(32, 1)
  635. g_extraweapon_items = ArrayCreate(32, 1)
  636. g_extraweapon_costs = ArrayCreate(1, 1)
  637. g_sky_names = ArrayCreate(32, 1)
  638. lights_thunder = ArrayCreate(32, 1)
  639. zombie_decals = ArrayCreate(1, 1)
  640. g_objective_ents = ArrayCreate(32, 1)
  641. g_extraitem_name = ArrayCreate(32, 1)
  642. g_extraitem_cost = ArrayCreate(1, 1)
  643. g_extraitem_team = ArrayCreate(1, 1)
  644. g_extraitem2_realname = ArrayCreate(32, 1)
  645. g_extraitem2_name = ArrayCreate(32, 1)
  646. g_extraitem2_cost = ArrayCreate(1, 1)
  647. g_extraitem2_team = ArrayCreate(1, 1)
  648. g_extraitem_new = ArrayCreate(1, 1)
  649. g_zclass_name = ArrayCreate(32, 1)
  650. g_zclass_info = ArrayCreate(32, 1)
  651. g_zclass_modelsstart = ArrayCreate(1, 1)
  652. g_zclass_modelsend = ArrayCreate(1, 1)
  653. g_zclass_playermodel = ArrayCreate(32, 1)
  654. g_zclass_modelindex = ArrayCreate(1, 1)
  655. g_zclass_clawmodel = ArrayCreate(32, 1)
  656. g_zclass_hp = ArrayCreate(1, 1)
  657. g_zclass_spd = ArrayCreate(1, 1)
  658. g_zclass_grav = ArrayCreate(1, 1)
  659. g_zclass_kb = ArrayCreate(1, 1)
  660. g_zclass2_realname = ArrayCreate(32, 1)
  661. g_zclass2_name = ArrayCreate(32, 1)
  662. g_zclass2_info = ArrayCreate(32, 1)
  663. g_zclass2_modelsstart = ArrayCreate(1, 1)
  664. g_zclass2_modelsend = ArrayCreate(1, 1)
  665. g_zclass2_playermodel = ArrayCreate(32, 1)
  666. g_zclass2_modelindex = ArrayCreate(1, 1)
  667. g_zclass2_clawmodel = ArrayCreate(32, 1)
  668. g_zclass2_hp = ArrayCreate(1, 1)
  669. g_zclass2_spd = ArrayCreate(1, 1)
  670. g_zclass2_grav = ArrayCreate(1, 1)
  671. g_zclass2_kb = ArrayCreate(1, 1)
  672. g_zclass_new = ArrayCreate(1, 1)
  673.  
  674. // Allow registering stuff now
  675. g_arrays_created = true
  676.  
  677. // Load customization data
  678. load_customization_from_files()
  679.  
  680. new i, buffer[100]
  681.  
  682. // Load up the hard coded extra items
  683. native_register_extra_item2("NightVision", g_extra_costs2[EXTRA_NVISION], ZP_TEAM_HUMAN)
  684. native_register_extra_item2("T-Virus Antidote", g_extra_costs2[EXTRA_ANTIDOTE], ZP_TEAM_ZOMBIE)
  685. native_register_extra_item2("Zombie Madness", g_extra_costs2[EXTRA_MADNESS], ZP_TEAM_ZOMBIE)
  686. native_register_extra_item2("Infection Bomb", g_extra_costs2[EXTRA_INFBOMB], ZP_TEAM_ZOMBIE)
  687.  
  688. // Extra weapons
  689. for (i = 0; i < ArraySize(g_extraweapon_names); i++)
  690. {
  691. ArrayGetString(g_extraweapon_names, i, buffer, charsmax(buffer))
  692. native_register_extra_item2(buffer, ArrayGetCell(g_extraweapon_costs, i), ZP_TEAM_HUMAN)
  693. }
  694.  
  695. // Custom player models
  696. for (i = 0; i < ArraySize(model_human); i++)
  697. {
  698. ArrayGetString(model_human, i, buffer, charsmax(buffer))
  699. format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
  700. ArrayPushCell(g_modelindex_human, engfunc(EngFunc_PrecacheModel, buffer))
  701. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
  702. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
  703. }
  704. for (i = 0; i < ArraySize(model_nemesis); i++)
  705. {
  706. ArrayGetString(model_nemesis, i, buffer, charsmax(buffer))
  707. format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
  708. ArrayPushCell(g_modelindex_nemesis, engfunc(EngFunc_PrecacheModel, buffer))
  709. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
  710. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
  711. }
  712. for (i = 0; i < ArraySize(model_survivor); i++)
  713. {
  714. ArrayGetString(model_survivor, i, buffer, charsmax(buffer))
  715. format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
  716. ArrayPushCell(g_modelindex_survivor, engfunc(EngFunc_PrecacheModel, buffer))
  717. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
  718. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
  719. }
  720. for (i = 0; i < ArraySize(model_admin_zombie); i++)
  721. {
  722. ArrayGetString(model_admin_zombie, i, buffer, charsmax(buffer))
  723. format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
  724. ArrayPushCell(g_modelindex_admin_zombie, engfunc(EngFunc_PrecacheModel, buffer))
  725. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
  726. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
  727. }
  728. for (i = 0; i < ArraySize(model_admin_human); i++)
  729. {
  730. ArrayGetString(model_admin_human, i, buffer, charsmax(buffer))
  731. format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
  732. ArrayPushCell(g_modelindex_admin_human, engfunc(EngFunc_PrecacheModel, buffer))
  733. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
  734. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
  735. }
  736.  
  737. // Custom weapon models
  738. engfunc(EngFunc_PrecacheModel, model_vknife_human)
  739. engfunc(EngFunc_PrecacheModel, model_vknife_nemesis)
  740. engfunc(EngFunc_PrecacheModel, model_vm249_survivor)
  741. engfunc(EngFunc_PrecacheModel, model_grenade_infect)
  742. engfunc(EngFunc_PrecacheModel, model_grenade_fire)
  743. engfunc(EngFunc_PrecacheModel, model_grenade_frost)
  744. engfunc(EngFunc_PrecacheModel, model_grenade_flare)
  745. engfunc(EngFunc_PrecacheModel, model_vknife_admin_human)
  746. engfunc(EngFunc_PrecacheModel, model_vknife_admin_zombie)
  747.  
  748. // Custom sprites for grenades
  749. g_trailSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_trail)
  750. g_exploSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_ring)
  751. g_flameSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_fire)
  752. g_smokeSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_smoke)
  753. g_glassSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_glass)
  754.  
  755. // Custom sounds
  756. for (i = 0; i < ArraySize(sound_win_zombies); i++)
  757. {
  758. ArrayGetString(sound_win_zombies, i, buffer, charsmax(buffer))
  759. engfunc(EngFunc_PrecacheSound, buffer)
  760. }
  761. for (i = 0; i < ArraySize(sound_win_humans); i++)
  762. {
  763. ArrayGetString(sound_win_humans, i, buffer, charsmax(buffer))
  764. engfunc(EngFunc_PrecacheSound, buffer)
  765. }
  766. for (i = 0; i < ArraySize(sound_win_no_one); i++)
  767. {
  768. ArrayGetString(sound_win_no_one, i, buffer, charsmax(buffer))
  769. engfunc(EngFunc_PrecacheSound, buffer)
  770. }
  771. for (i = 0; i < ArraySize(zombie_infect); i++)
  772. {
  773. ArrayGetString(zombie_infect, i, buffer, charsmax(buffer))
  774. engfunc(EngFunc_PrecacheSound, buffer)
  775. }
  776. for (i = 0; i < ArraySize(zombie_pain); i++)
  777. {
  778. ArrayGetString(zombie_pain, i, buffer, charsmax(buffer))
  779. engfunc(EngFunc_PrecacheSound, buffer)
  780. }
  781. for (i = 0; i < ArraySize(nemesis_pain); i++)
  782. {
  783. ArrayGetString(nemesis_pain, i, buffer, charsmax(buffer))
  784. engfunc(EngFunc_PrecacheSound, buffer)
  785. }
  786. for (i = 0; i < ArraySize(zombie_die); i++)
  787. {
  788. ArrayGetString(zombie_die, i, buffer, charsmax(buffer))
  789. engfunc(EngFunc_PrecacheSound, buffer)
  790. }
  791. for (i = 0; i < ArraySize(zombie_fall); i++)
  792. {
  793. ArrayGetString(zombie_fall, i, buffer, charsmax(buffer))
  794. engfunc(EngFunc_PrecacheSound, buffer)
  795. }
  796. for (i = 0; i < ArraySize(zombie_miss_slash); i++)
  797. {
  798. ArrayGetString(zombie_miss_slash, i, buffer, charsmax(buffer))
  799. engfunc(EngFunc_PrecacheSound, buffer)
  800. }
  801. for (i = 0; i < ArraySize(zombie_miss_wall); i++)
  802. {
  803. ArrayGetString(zombie_miss_wall, i, buffer, charsmax(buffer))
  804. engfunc(EngFunc_PrecacheSound, buffer)
  805. }
  806. for (i = 0; i < ArraySize(zombie_hit_normal); i++)
  807. {
  808. ArrayGetString(zombie_hit_normal, i, buffer, charsmax(buffer))
  809. engfunc(EngFunc_PrecacheSound, buffer)
  810. }
  811. for (i = 0; i < ArraySize(zombie_hit_stab); i++)
  812. {
  813. ArrayGetString(zombie_hit_stab, i, buffer, charsmax(buffer))
  814. engfunc(EngFunc_PrecacheSound, buffer)
  815. }
  816. for (i = 0; i < ArraySize(zombie_idle); i++)
  817. {
  818. ArrayGetString(zombie_idle, i, buffer, charsmax(buffer))
  819. engfunc(EngFunc_PrecacheSound, buffer)
  820. }
  821. for (i = 0; i < ArraySize(zombie_idle_last); i++)
  822. {
  823. ArrayGetString(zombie_idle_last, i, buffer, charsmax(buffer))
  824. engfunc(EngFunc_PrecacheSound, buffer)
  825. }
  826. for (i = 0; i < ArraySize(zombie_madness); i++)
  827. {
  828. ArrayGetString(zombie_madness, i, buffer, charsmax(buffer))
  829. engfunc(EngFunc_PrecacheSound, buffer)
  830. }
  831. for (i = 0; i < ArraySize(sound_nemesis); i++)
  832. {
  833. ArrayGetString(sound_nemesis, i, buffer, charsmax(buffer))
  834. engfunc(EngFunc_PrecacheSound, buffer)
  835. }
  836. for (i = 0; i < ArraySize(sound_survivor); i++)
  837. {
  838. ArrayGetString(sound_survivor, i, buffer, charsmax(buffer))
  839. engfunc(EngFunc_PrecacheSound, buffer)
  840. }
  841. for (i = 0; i < ArraySize(sound_swarm); i++)
  842. {
  843. ArrayGetString(sound_swarm, i, buffer, charsmax(buffer))
  844. engfunc(EngFunc_PrecacheSound, buffer)
  845. }
  846. for (i = 0; i < ArraySize(sound_multi); i++)
  847. {
  848. ArrayGetString(sound_multi, i, buffer, charsmax(buffer))
  849. engfunc(EngFunc_PrecacheSound, buffer)
  850. }
  851. for (i = 0; i < ArraySize(sound_plague); i++)
  852. {
  853. ArrayGetString(sound_plague, i, buffer, charsmax(buffer))
  854. engfunc(EngFunc_PrecacheSound, buffer)
  855. }
  856. for (i = 0; i < ArraySize(grenade_infect); i++)
  857. {
  858. ArrayGetString(grenade_infect, i, buffer, charsmax(buffer))
  859. engfunc(EngFunc_PrecacheSound, buffer)
  860. }
  861. for (i = 0; i < ArraySize(grenade_infect_player); i++)
  862. {
  863. ArrayGetString(grenade_infect_player, i, buffer, charsmax(buffer))
  864. engfunc(EngFunc_PrecacheSound, buffer)
  865. }
  866. for (i = 0; i < ArraySize(grenade_fire); i++)
  867. {
  868. ArrayGetString(grenade_fire, i, buffer, charsmax(buffer))
  869. engfunc(EngFunc_PrecacheSound, buffer)
  870. }
  871. for (i = 0; i < ArraySize(grenade_fire_player); i++)
  872. {
  873. ArrayGetString(grenade_fire_player, i, buffer, charsmax(buffer))
  874. engfunc(EngFunc_PrecacheSound, buffer)
  875. }
  876. for (i = 0; i < ArraySize(grenade_frost); i++)
  877. {
  878. ArrayGetString(grenade_frost, i, buffer, charsmax(buffer))
  879. engfunc(EngFunc_PrecacheSound, buffer)
  880. }
  881. for (i = 0; i < ArraySize(grenade_frost_player); i++)
  882. {
  883. ArrayGetString(grenade_frost_player, i, buffer, charsmax(buffer))
  884. engfunc(EngFunc_PrecacheSound, buffer)
  885. }
  886. for (i = 0; i < ArraySize(grenade_frost_break); i++)
  887. {
  888. ArrayGetString(grenade_frost_break, i, buffer, charsmax(buffer))
  889. engfunc(EngFunc_PrecacheSound, buffer)
  890. }
  891. for (i = 0; i < ArraySize(grenade_flare); i++)
  892. {
  893. ArrayGetString(grenade_flare, i, buffer, charsmax(buffer))
  894. engfunc(EngFunc_PrecacheSound, buffer)
  895. }
  896. for (i = 0; i < ArraySize(sound_antidote); i++)
  897. {
  898. ArrayGetString(sound_antidote, i, buffer, charsmax(buffer))
  899. engfunc(EngFunc_PrecacheSound, buffer)
  900. }
  901. for (i = 0; i < ArraySize(sound_thunder); i++)
  902. {
  903. ArrayGetString(sound_thunder, i, buffer, charsmax(buffer))
  904. engfunc(EngFunc_PrecacheSound, buffer)
  905. }
  906.  
  907. // Ambience Sounds
  908. if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION])
  909. {
  910. for (i = 0; i < ArraySize(sound_ambience1); i++)
  911. {
  912. ArrayGetString(sound_ambience1, i, buffer, charsmax(buffer))
  913.  
  914. if (ArrayGetCell(sound_ambience1_ismp3, i))
  915. {
  916. format(buffer, charsmax(buffer), "sound/%s", buffer)
  917. engfunc(EngFunc_PrecacheGeneric, buffer)
  918. }
  919. else
  920. {
  921. engfunc(EngFunc_PrecacheSound, buffer)
  922. }
  923. }
  924. }
  925. if (g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS])
  926. {
  927. for (i = 0; i < ArraySize(sound_ambience2); i++)
  928. {
  929. ArrayGetString(sound_ambience2, i, buffer, charsmax(buffer))
  930.  
  931. if (ArrayGetCell(sound_ambience2_ismp3, i))
  932. {
  933. format(buffer, charsmax(buffer), "sound/%s", buffer)
  934. engfunc(EngFunc_PrecacheGeneric, buffer)
  935. }
  936. else
  937. {
  938. engfunc(EngFunc_PrecacheSound, buffer)
  939. }
  940. }
  941. }
  942. if (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR])
  943. {
  944. for (i = 0; i < ArraySize(sound_ambience3); i++)
  945. {
  946. ArrayGetString(sound_ambience3, i, buffer, charsmax(buffer))
  947.  
  948. if (ArrayGetCell(sound_ambience3_ismp3, i))
  949. {
  950. format(buffer, charsmax(buffer), "sound/%s", buffer)
  951. engfunc(EngFunc_PrecacheGeneric, buffer)
  952. }
  953. else
  954. {
  955. engfunc(EngFunc_PrecacheSound, buffer)
  956. }
  957. }
  958. }
  959. if (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM])
  960. {
  961. for (i = 0; i < ArraySize(sound_ambience4); i++)
  962. {
  963. ArrayGetString(sound_ambience4, i, buffer, charsmax(buffer))
  964.  
  965. if (ArrayGetCell(sound_ambience4_ismp3, i))
  966. {
  967. format(buffer, charsmax(buffer), "sound/%s", buffer)
  968. engfunc(EngFunc_PrecacheGeneric, buffer)
  969. }
  970. else
  971. {
  972. engfunc(EngFunc_PrecacheSound, buffer)
  973. }
  974. }
  975. }
  976. if (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE])
  977. {
  978. for (i = 0; i < ArraySize(sound_ambience5); i++)
  979. {
  980. ArrayGetString(sound_ambience5, i, buffer, charsmax(buffer))
  981.  
  982. if (ArrayGetCell(sound_ambience5_ismp3, i))
  983. {
  984. format(buffer, charsmax(buffer), "sound/%s", buffer)
  985. engfunc(EngFunc_PrecacheGeneric, buffer)
  986. }
  987. else
  988. {
  989. engfunc(EngFunc_PrecacheSound, buffer)
  990. }
  991. }
  992. }
  993.  
  994. // CS sounds (just in case)
  995. engfunc(EngFunc_PrecacheSound, sound_flashlight)
  996. engfunc(EngFunc_PrecacheSound, sound_buyammo)
  997. engfunc(EngFunc_PrecacheSound, sound_armorhit)
  998.  
  999. new ent
  1000.  
  1001. // Fake Hostage (to force round ending)
  1002. ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "hostage_entity"))
  1003. if (pev_valid(ent))
  1004. {
  1005. engfunc(EngFunc_SetOrigin, ent, Float:{8192.0,8192.0,8192.0})
  1006. dllfunc(DLLFunc_Spawn, ent)
  1007. }
  1008.  
  1009. // Weather/ambience effects
  1010. if (g_ambience_fog)
  1011. {
  1012. ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_fog"))
  1013. if (pev_valid(ent))
  1014. {
  1015. fm_set_kvd(ent, "density", g_fog_density, "env_fog")
  1016. fm_set_kvd(ent, "rendercolor", g_fog_color, "env_fog")
  1017. }
  1018. }
  1019. if (g_ambience_rain) engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_rain"))
  1020. if (g_ambience_snow) engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_snow"))
  1021.  
  1022. // Prevent some entities from spawning
  1023. g_fwSpawn = register_forward(FM_Spawn, "fw_Spawn")
  1024.  
  1025. // Prevent hostage sounds from being precached
  1026. g_fwPrecacheSound = register_forward(FM_PrecacheSound, "fw_PrecacheSound")
  1027. }
  1028.  
  1029. public plugin_init()
  1030. {
  1031. // Plugin disabled?
  1032. if (!g_pluginenabled) return;
  1033.  
  1034. // No zombie classes?
  1035. if (!g_zclass_i) set_fail_state("No zombie classes loaded!")
  1036.  
  1037. // Language files
  1038. register_dictionary("zombie_plague.txt")
  1039.  
  1040. // Events
  1041. register_event("HLTV", "event_round_start", "a", "1=0", "2=0")
  1042. register_logevent("logevent_round_start",2, "1=Round_Start")
  1043. register_logevent("logevent_round_end", 2, "1=Round_End")
  1044. register_event("AmmoX", "event_ammo_x", "be")
  1045. if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] || g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] || g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] || g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] || g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE])
  1046. register_event("30", "event_intermission", "a")
  1047.  
  1048. // HAM Forwards
  1049. RegisterHam(Ham_Spawn, "player", "fw_PlayerSpawn_Post", 1)
  1050. RegisterHam(Ham_Killed, "player", "fw_PlayerKilled")
  1051. RegisterHam(Ham_Killed, "player", "fw_PlayerKilled_Post", 1)
  1052. RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage")
  1053. RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage_Post", 1)
  1054. RegisterHam(Ham_TraceAttack, "player", "fw_TraceAttack")
  1055. RegisterHam(Ham_Use, "func_tank", "fw_UseStationary")
  1056. RegisterHam(Ham_Use, "func_tankmortar", "fw_UseStationary")
  1057. RegisterHam(Ham_Use, "func_tankrocket", "fw_UseStationary")
  1058. RegisterHam(Ham_Use, "func_tanklaser", "fw_UseStationary")
  1059. RegisterHam(Ham_Use, "func_tank", "fw_UseStationary_Post", 1)
  1060. RegisterHam(Ham_Use, "func_tankmortar", "fw_UseStationary_Post", 1)
  1061. RegisterHam(Ham_Use, "func_tankrocket", "fw_UseStationary_Post", 1)
  1062. RegisterHam(Ham_Use, "func_tanklaser", "fw_UseStationary_Post", 1)
  1063. RegisterHam(Ham_Use, "func_pushable", "fw_UsePushable")
  1064. RegisterHam(Ham_Touch, "weaponbox", "fw_TouchWeapon")
  1065. RegisterHam(Ham_Touch, "armoury_entity", "fw_TouchWeapon")
  1066. RegisterHam(Ham_Touch, "weapon_shield", "fw_TouchWeapon")
  1067. RegisterHam(Ham_AddPlayerItem, "player", "fw_AddPlayerItem")
  1068. for (new i = 1; i < sizeof WEAPONENTNAMES; i++)
  1069. if (WEAPONENTNAMES[i][0]) RegisterHam(Ham_Item_Deploy, WEAPONENTNAMES[i], "fw_Item_Deploy_Post", 1)
  1070.  
  1071. // FM Forwards
  1072. register_forward(FM_ClientDisconnect, "fw_ClientDisconnect")
  1073. register_forward(FM_ClientDisconnect, "fw_ClientDisconnect_Post", 1)
  1074. register_forward(FM_ClientKill, "fw_ClientKill")
  1075. register_forward(FM_EmitSound, "fw_EmitSound")
  1076. if (!g_handle_models_on_separate_ent) register_forward(FM_SetClientKeyValue, "fw_SetClientKeyValue")
  1077. register_forward(FM_ClientUserInfoChanged, "fw_ClientUserInfoChanged")
  1078. register_forward(FM_GetGameDescription, "fw_GetGameDescription")
  1079. register_forward(FM_SetModel, "fw_SetModel")
  1080. RegisterHam(Ham_Think, "grenade", "fw_ThinkGrenade")
  1081. register_forward(FM_CmdStart, "fw_CmdStart")
  1082. register_forward(FM_PlayerPreThink, "fw_PlayerPreThink")
  1083. unregister_forward(FM_Spawn, g_fwSpawn)
  1084. unregister_forward(FM_PrecacheSound, g_fwPrecacheSound)
  1085.  
  1086. // Client commands
  1087. register_clcmd("say zpmenu", "clcmd_saymenu")
  1088. register_clcmd("say /zpmenu", "clcmd_saymenu")
  1089. register_clcmd("say unstuck", "clcmd_sayunstuck")
  1090. register_clcmd("say /unstuck", "clcmd_sayunstuck")
  1091. register_clcmd("nightvision", "clcmd_nightvision")
  1092. register_clcmd("drop", "clcmd_drop")
  1093. register_clcmd("buyammo1", "clcmd_buyammo")
  1094. register_clcmd("buyammo2", "clcmd_buyammo")
  1095. register_clcmd("chooseteam", "clcmd_changeteam")
  1096. register_clcmd("jointeam", "clcmd_changeteam")
  1097.  
  1098. // Menus
  1099. register_menu("Game Menu", KEYSMENU, "menu_game")
  1100. register_menu("Buy Menu 1", KEYSMENU, "menu_buy1")
  1101. register_menu("Buy Menu 2", KEYSMENU, "menu_buy2")
  1102. register_menu("Mod Info", KEYSMENU, "menu_info")
  1103. register_menu("Admin Menu", KEYSMENU, "menu_admin")
  1104.  
  1105. // Admin commands
  1106. register_concmd("zp_zombie", "cmd_zombie", _, "<target> - Turn someone into a Zombie", 0)
  1107. register_concmd("zp_human", "cmd_human", _, "<target> - Turn someone back to Human", 0)
  1108. register_concmd("zp_nemesis", "cmd_nemesis", _, "<target> - Turn someone into a Nemesis", 0)
  1109. register_concmd("zp_survivor", "cmd_survivor", _, "<target> - Turn someone into a Survivor", 0)
  1110. register_concmd("zp_respawn", "cmd_respawn", _, "<target> - Respawn someone", 0)
  1111. register_concmd("zp_swarm", "cmd_swarm", _, " - Start Swarm Mode", 0)
  1112. register_concmd("zp_multi", "cmd_multi", _, " - Start Multi Infection", 0)
  1113. register_concmd("zp_plague", "cmd_plague", _, " - Start Plague Mode", 0)
  1114.  
  1115. // Message IDs
  1116. g_msgScoreInfo = get_user_msgid("ScoreInfo")
  1117. g_msgTeamInfo = get_user_msgid("TeamInfo")
  1118. g_msgDeathMsg = get_user_msgid("DeathMsg")
  1119. g_msgScoreAttrib = get_user_msgid("ScoreAttrib")
  1120. g_msgSetFOV = get_user_msgid("SetFOV")
  1121. g_msgScreenFade = get_user_msgid("ScreenFade")
  1122. g_msgScreenShake = get_user_msgid("ScreenShake")
  1123. g_msgNVGToggle = get_user_msgid("NVGToggle")
  1124. g_msgFlashlight = get_user_msgid("Flashlight")
  1125. g_msgFlashBat = get_user_msgid("FlashBat")
  1126. g_msgAmmoPickup = get_user_msgid("AmmoPickup")
  1127. g_msgDamage = get_user_msgid("Damage")
  1128. g_msgHideWeapon = get_user_msgid("HideWeapon")
  1129. g_msgCrosshair = get_user_msgid("Crosshair")
  1130. g_msgSayText = get_user_msgid("SayText")
  1131. g_msgCurWeapon = get_user_msgid("CurWeapon")
  1132.  
  1133. // Message hooks
  1134. register_message(g_msgCurWeapon, "message_cur_weapon")
  1135. register_message(get_user_msgid("Money"), "message_money")
  1136. register_message(get_user_msgid("Health"), "message_health")
  1137. register_message(g_msgFlashBat, "message_flashbat")
  1138. register_message(g_msgScreenFade, "message_screenfade")
  1139. register_message(g_msgNVGToggle, "message_nvgtoggle")
  1140. if (g_handle_models_on_separate_ent) register_message(get_user_msgid("ClCorpse"), "message_clcorpse")
  1141. register_message(get_user_msgid("WeapPickup"), "message_weappickup")
  1142. register_message(g_msgAmmoPickup, "message_ammopickup")
  1143. register_message(get_user_msgid("Scenario"), "message_scenario")
  1144. register_message(get_user_msgid("HostagePos"), "message_hostagepos")
  1145. register_message(get_user_msgid("TextMsg"), "message_textmsg")
  1146. register_message(get_user_msgid("SendAudio"), "message_sendaudio")
  1147. register_message(get_user_msgid("TeamScore"), "message_teamscore")
  1148. register_message(g_msgTeamInfo, "message_teaminfo")
  1149.  
  1150. // CVARS - General Purpose
  1151. cvar_warmup = register_cvar("zp_delay", "10")
  1152. cvar_lighting = register_cvar("zp_lighting", "a")
  1153. cvar_thunder = register_cvar("zp_thunderclap", "90")
  1154. cvar_triggered = register_cvar("zp_triggered_lights", "1")
  1155. cvar_removedoors = register_cvar("zp_remove_doors", "0")
  1156. cvar_blockpushables = register_cvar("zp_blockuse_pushables", "1")
  1157. cvar_blocksuicide = register_cvar("zp_block_suicide", "1")
  1158. cvar_randspawn = register_cvar("zp_random_spawn", "1")
  1159. cvar_respawnworldspawnkill = register_cvar("zp_respawn_on_worldspawn_kill", "1")
  1160. cvar_removedropped = register_cvar("zp_remove_dropped", "0")
  1161. cvar_removemoney = register_cvar("zp_remove_money", "1")
  1162. cvar_buycustom = register_cvar("zp_buy_custom", "1")
  1163. cvar_randweapons = register_cvar("zp_random_weapons", "0")
  1164. cvar_adminmodelshuman = register_cvar("zp_admin_models_human", "1")
  1165. cvar_adminknifemodelshuman = register_cvar("zp_admin_knife_models_human", "0")
  1166. cvar_adminmodelszombie = register_cvar("zp_admin_models_zombie", "1")
  1167. cvar_adminknifemodelszombie = register_cvar("zp_admin_knife_models_zombie", "0")
  1168. cvar_zclasses = register_cvar("zp_zombie_classes", "1")
  1169. cvar_statssave = register_cvar("zp_stats_save", "1")
  1170. cvar_startammopacks = register_cvar("zp_starting_ammo_packs", "5")
  1171. cvar_preventconsecutive = register_cvar("zp_prevent_consecutive_modes", "1")
  1172. cvar_keephealthondisconnect = register_cvar("zp_keep_health_on_disconnect", "1")
  1173.  
  1174. // CVARS - Deathmatch
  1175. cvar_deathmatch = register_cvar("zp_deathmatch", "0")
  1176. cvar_spawndelay = register_cvar("zp_spawn_delay", "5")
  1177. cvar_spawnprotection = register_cvar("zp_spawn_protection", "5")
  1178. cvar_respawnonsuicide = register_cvar("zp_respawn_on_suicide", "0")
  1179. cvar_respawnafterlast = register_cvar("zp_respawn_after_last_human", "1")
  1180. cvar_allowrespawninfection = register_cvar("zp_infection_allow_respawn", "1")
  1181. cvar_allowrespawnnem = register_cvar("zp_nem_allow_respawn", "0")
  1182. cvar_allowrespawnsurv = register_cvar("zp_surv_allow_respawn", "0")
  1183. cvar_allowrespawnswarm = register_cvar("zp_swarm_allow_respawn", "0")
  1184. cvar_allowrespawnplague = register_cvar("zp_plague_allow_respawn", "0")
  1185. cvar_respawnzomb = register_cvar("zp_respawn_zombies", "1")
  1186. cvar_respawnhum = register_cvar("zp_respawn_humans", "1")
  1187. cvar_respawnnem = register_cvar("zp_respawn_nemesis", "1")
  1188. cvar_respawnsurv = register_cvar("zp_respawn_survivors", "1")
  1189.  
  1190. // CVARS - Extra Items
  1191. cvar_extraitems = register_cvar("zp_extra_items", "1")
  1192. cvar_extraweapons = register_cvar("zp_extra_weapons", "1")
  1193. cvar_extranvision = register_cvar("zp_extra_nvision", "1")
  1194. cvar_extraantidote = register_cvar("zp_extra_antidote", "1")
  1195. cvar_antidotelimit = register_cvar("zp_extra_antidote_limit", "999")
  1196. cvar_extramadness = register_cvar("zp_extra_madness", "1")
  1197. cvar_madnesslimit = register_cvar("zp_extra_madness_limit", "999")
  1198. cvar_madnessduration = register_cvar("zp_extra_madness_duration", "5.0")
  1199. cvar_extrainfbomb = register_cvar("zp_extra_infbomb", "1")
  1200. cvar_infbomblimit = register_cvar("zp_extra_infbomb_limit", "999")
  1201.  
  1202. // CVARS - Flashlight and Nightvision
  1203. cvar_nvggive = register_cvar("zp_nvg_give", "1")
  1204. cvar_customnvg = register_cvar("zp_nvg_custom", "1")
  1205. cvar_nvgsize = register_cvar("zp_nvg_size", "80")
  1206. cvar_nvgcolor[0] = register_cvar("zp_nvg_color_R", "0")
  1207. cvar_nvgcolor[1] = register_cvar("zp_nvg_color_G", "150")
  1208. cvar_nvgcolor[2] = register_cvar("zp_nvg_color_B", "0")
  1209. cvar_humnvgcolor[0] = register_cvar("zp_nvg_hum_color_R", "0")
  1210. cvar_humnvgcolor[1] = register_cvar("zp_nvg_hum_color_G", "150")
  1211. cvar_humnvgcolor[2] = register_cvar("zp_nvg_hum_color_B", "0")
  1212. cvar_nemnvgcolor[0] = register_cvar("zp_nvg_nem_color_R", "150")
  1213. cvar_nemnvgcolor[1] = register_cvar("zp_nvg_nem_color_G", "0")
  1214. cvar_nemnvgcolor[2] = register_cvar("zp_nvg_nem_color_B", "0")
  1215. cvar_customflash = register_cvar("zp_flash_custom", "0")
  1216. cvar_flashsize = register_cvar("zp_flash_size", "10")
  1217. cvar_flashdrain = register_cvar("zp_flash_drain", "1")
  1218. cvar_flashcharge = register_cvar("zp_flash_charge", "5")
  1219. cvar_flashdist = register_cvar("zp_flash_distance", "1000")
  1220. cvar_flashcolor[0] = register_cvar("zp_flash_color_R", "100")
  1221. cvar_flashcolor[1] = register_cvar("zp_flash_color_G", "100")
  1222. cvar_flashcolor[2] = register_cvar("zp_flash_color_B", "100")
  1223. cvar_flashshowall = register_cvar("zp_flash_show_all", "1")
  1224.  
  1225. // CVARS - Knockback
  1226. cvar_knockback = register_cvar("zp_knockback", "0")
  1227. cvar_knockbackdamage = register_cvar("zp_knockback_damage", "1")
  1228. cvar_knockbackpower = register_cvar("zp_knockback_power", "1")
  1229. cvar_knockbackzvel = register_cvar("zp_knockback_zvel", "0")
  1230. cvar_knockbackducking = register_cvar("zp_knockback_ducking", "0.25")
  1231. cvar_knockbackdist = register_cvar("zp_knockback_distance", "500")
  1232. cvar_nemknockback = register_cvar("zp_knockback_nemesis", "0.25")
  1233.  
  1234. // CVARS - Leap
  1235. cvar_leapzombies = register_cvar("zp_leap_zombies", "0")
  1236. cvar_leapzombiesforce = register_cvar("zp_leap_zombies_force", "500")
  1237. cvar_leapzombiesheight = register_cvar("zp_leap_zombies_height", "300")
  1238. cvar_leapzombiescooldown = register_cvar("zp_leap_zombies_cooldown", "5.0")
  1239. cvar_leapnemesis = register_cvar("zp_leap_nemesis", "1")
  1240. cvar_leapnemesisforce = register_cvar("zp_leap_nemesis_force", "500")
  1241. cvar_leapnemesisheight = register_cvar("zp_leap_nemesis_height", "300")
  1242. cvar_leapnemesiscooldown = register_cvar("zp_leap_nemesis_cooldown", "5.0")
  1243. cvar_leapsurvivor = register_cvar("zp_leap_survivor", "0")
  1244. cvar_leapsurvivorforce = register_cvar("zp_leap_survivor_force", "500")
  1245. cvar_leapsurvivorheight = register_cvar("zp_leap_survivor_height", "300")
  1246. cvar_leapsurvivorcooldown = register_cvar("zp_leap_survivor_cooldown", "5.0")
  1247.  
  1248. // CVARS - Humans
  1249. cvar_humanhp = register_cvar("zp_human_health", "100")
  1250. cvar_humanlasthp = register_cvar("zp_human_last_extrahp", "0")
  1251. cvar_humanspd = register_cvar("zp_human_speed", "240")
  1252. cvar_humangravity = register_cvar("zp_human_gravity", "1.0")
  1253. cvar_humanarmor = register_cvar("zp_human_armor_protect", "1")
  1254. cvar_infammo = register_cvar("zp_human_unlimited_ammo", "0")
  1255. cvar_ammodamage = register_cvar("zp_human_damage_reward", "500")
  1256. cvar_fragskill = register_cvar("zp_human_frags_for_kill", "1")
  1257.  
  1258. // CVARS - Custom Grenades
  1259. cvar_firegrenades = register_cvar("zp_fire_grenades", "1")
  1260. cvar_fireduration = register_cvar("zp_fire_duration", "10")
  1261. cvar_firedamage = register_cvar("zp_fire_damage", "5")
  1262. cvar_fireslowdown = register_cvar("zp_fire_slowdown", "0.5")
  1263. cvar_frostgrenades = register_cvar("zp_frost_grenades", "1")
  1264. cvar_freezeduration = register_cvar("zp_frost_duration", "3")
  1265. cvar_flaregrenades = register_cvar("zp_flare_grenades","1")
  1266. cvar_flareduration = register_cvar("zp_flare_duration", "60")
  1267. cvar_flaresize = register_cvar("zp_flare_size", "25")
  1268. cvar_flarecolor = register_cvar("zp_flare_color", "0")
  1269.  
  1270. // CVARS - Zombies
  1271. cvar_zombiefirsthp = register_cvar("zp_zombie_first_hp", "2.0")
  1272. cvar_zombiearmor = register_cvar("zp_zombie_armor", "0.75")
  1273. cvar_hitzones = register_cvar("zp_zombie_hitzones", "0")
  1274. cvar_zombiebonushp = register_cvar("zp_zombie_infect_health", "100")
  1275. cvar_zombiefov = register_cvar("zp_zombie_fov", "110")
  1276. cvar_zombiesilent = register_cvar("zp_zombie_silent", "1")
  1277. cvar_zombiepainfree = register_cvar("zp_zombie_painfree", "2")
  1278. cvar_zombiebleeding = register_cvar("zp_zombie_bleeding", "1")
  1279. cvar_ammoinfect = register_cvar("zp_zombie_infect_reward", "1")
  1280. cvar_fragsinfect = register_cvar("zp_zombie_frags_for_infect", "1")
  1281.  
  1282. // CVARS - Special Effects
  1283. cvar_infectionscreenfade = register_cvar("zp_infection_screenfade", "1")
  1284. cvar_infectionscreenshake = register_cvar("zp_infection_screenshake", "1")
  1285. cvar_infectionsparkle = register_cvar("zp_infection_sparkle", "1")
  1286. cvar_infectiontracers = register_cvar("zp_infection_tracers", "1")
  1287. cvar_infectionparticles = register_cvar("zp_infection_particles", "1")
  1288. cvar_hudicons = register_cvar("zp_hud_icons", "1")
  1289.  
  1290. // CVARS - Nemesis
  1291. cvar_nem = register_cvar("zp_nem_enabled", "1")
  1292. cvar_nemchance = register_cvar("zp_nem_chance", "20")
  1293. cvar_nemminplayers = register_cvar("zp_nem_min_players", "0")
  1294. cvar_nemhp = register_cvar("zp_nem_health", "0")
  1295. cvar_nembasehp = register_cvar("zp_nem_base_health", "0")
  1296. cvar_nemspd = register_cvar("zp_nem_speed", "250")
  1297. cvar_nemgravity = register_cvar("zp_nem_gravity", "0.5")
  1298. cvar_nemdamage = register_cvar("zp_nem_damage", "250")
  1299. cvar_nemglow = register_cvar("zp_nem_glow", "1")
  1300. cvar_nemaura = register_cvar("zp_nem_aura", "1")
  1301. cvar_nempainfree = register_cvar("zp_nem_painfree", "0")
  1302. cvar_nemignorefrags = register_cvar("zp_nem_ignore_frags", "1")
  1303. cvar_nemignoreammo = register_cvar("zp_nem_ignore_rewards", "1")
  1304.  
  1305. // CVARS - Survivor
  1306. cvar_surv = register_cvar("zp_surv_enabled", "1")
  1307. cvar_survchance = register_cvar("zp_surv_chance", "20")
  1308. cvar_survminplayers = register_cvar("zp_surv_min_players", "0")
  1309. cvar_survhp = register_cvar("zp_surv_health", "0")
  1310. cvar_survbasehp = register_cvar("zp_surv_base_health", "0")
  1311. cvar_survspd = register_cvar("zp_surv_speed", "230")
  1312. cvar_survgravity = register_cvar("zp_surv_gravity", "1.25")
  1313. cvar_survglow = register_cvar("zp_surv_glow", "1")
  1314. cvar_survaura = register_cvar("zp_surv_aura", "1")
  1315. cvar_survpainfree = register_cvar("zp_surv_painfree", "1")
  1316. cvar_survignorefrags = register_cvar("zp_surv_ignore_frags", "1")
  1317. cvar_survignoreammo = register_cvar("zp_surv_ignore_rewards", "1")
  1318. cvar_survweapon = register_cvar("zp_surv_weapon", "weapon_m249")
  1319. cvar_survinfammo = register_cvar("zp_surv_unlimited_ammo", "2")
  1320.  
  1321. // CVARS - Swarm Mode
  1322. cvar_swarm = register_cvar("zp_swarm_enabled", "1")
  1323. cvar_swarmchance = register_cvar("zp_swarm_chance", "20")
  1324. cvar_swarmminplayers = register_cvar("zp_swarm_min_players", "0")
  1325.  
  1326. // CVARS - Multi Infection
  1327. cvar_multi = register_cvar("zp_multi_enabled", "1")
  1328. cvar_multichance = register_cvar("zp_multi_chance", "20")
  1329. cvar_multiminplayers = register_cvar("zp_multi_min_players", "0")
  1330. cvar_multiratio = register_cvar("zp_multi_ratio", "0.15")
  1331.  
  1332. // CVARS - Plague Mode
  1333. cvar_plague = register_cvar("zp_plague_enabled", "1")
  1334. cvar_plaguechance = register_cvar("zp_plague_chance", "30")
  1335. cvar_plagueminplayers = register_cvar("zp_plague_min_players", "0")
  1336. cvar_plagueratio = register_cvar("zp_plague_ratio", "0.5")
  1337. cvar_plaguenemnum = register_cvar("zp_plague_nem_number", "1")
  1338. cvar_plaguenemhpmulti = register_cvar("zp_plague_nem_hp_multi", "0.5")
  1339. cvar_plaguesurvnum = register_cvar("zp_plague_surv_number", "1")
  1340. cvar_plaguesurvhpmulti = register_cvar("zp_plague_surv_hp_multi", "0.5")
  1341.  
  1342. // CVARS - Others
  1343. cvar_logcommands = register_cvar("zp_logcommands", "1")
  1344. cvar_showactivity = get_cvar_pointer("amx_show_activity")
  1345. cvar_botquota = get_cvar_pointer("bot_quota")
  1346. register_cvar("zp_version", PLUGIN_VERSION, FCVAR_SERVER|FCVAR_SPONLY)
  1347. set_cvar_string("zp_version", PLUGIN_VERSION)
  1348.  
  1349. // Custom Forwards
  1350. g_fwRoundStart = CreateMultiForward("zp_round_started", ET_IGNORE, FP_CELL, FP_CELL)
  1351. g_fwRoundEnd = CreateMultiForward("zp_round_ended", ET_IGNORE, FP_CELL)
  1352. g_fwUserInfected_pre = CreateMultiForward("zp_user_infected_pre", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL)
  1353. g_fwUserInfected_post = CreateMultiForward("zp_user_infected_post", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL)
  1354. g_fwUserHumanized_pre = CreateMultiForward("zp_user_humanized_pre", ET_IGNORE, FP_CELL, FP_CELL)
  1355. g_fwUserHumanized_post = CreateMultiForward("zp_user_humanized_post", ET_IGNORE, FP_CELL, FP_CELL)
  1356. g_fwUserInfect_attempt = CreateMultiForward("zp_user_infect_attempt", ET_CONTINUE, FP_CELL, FP_CELL, FP_CELL)
  1357. g_fwUserHumanize_attempt = CreateMultiForward("zp_user_humanize_attempt", ET_CONTINUE, FP_CELL, FP_CELL)
  1358. g_fwExtraItemSelected = CreateMultiForward("zp_extra_item_selected", ET_CONTINUE, FP_CELL, FP_CELL)
  1359. g_fwUserUnfrozen = CreateMultiForward("zp_user_unfrozen", ET_IGNORE, FP_CELL)
  1360. g_fwUserLastZombie = CreateMultiForward("zp_user_last_zombie", ET_IGNORE, FP_CELL)
  1361. g_fwUserLastHuman = CreateMultiForward("zp_user_last_human", ET_IGNORE, FP_CELL)
  1362.  
  1363. // Collect random spawn points
  1364. load_spawns()
  1365.  
  1366. // Set a random skybox?
  1367. if (g_sky_enable)
  1368. {
  1369. new sky[32]
  1370. ArrayGetString(g_sky_names, random_num(0, ArraySize(g_sky_names) - 1), sky, charsmax(sky))
  1371. set_cvar_string("sv_skyname", sky)
  1372. }
  1373.  
  1374. // Disable sky lighting so it doesn't mess with our custom lighting
  1375. set_cvar_num("sv_skycolor_r", 0)
  1376. set_cvar_num("sv_skycolor_g", 0)
  1377. set_cvar_num("sv_skycolor_b", 0)
  1378.  
  1379. // Create the HUD Sync Objects
  1380. g_MsgSync = CreateHudSyncObj()
  1381. g_MsgSync2 = CreateHudSyncObj()
  1382.  
  1383. // Format mod name
  1384. formatex(g_modname, charsmax(g_modname), "Zombie Plague %s", PLUGIN_VERSION)
  1385.  
  1386. // Get Max Players
  1387. g_maxplayers = get_maxplayers()
  1388.  
  1389. // Reserved saving slots starts on maxplayers+1
  1390. db_slot_i = g_maxplayers+1
  1391.  
  1392. // Check if it's a CZ server
  1393. new mymod[6]
  1394. get_modname(mymod, charsmax(mymod))
  1395. if (equal(mymod, "czero")) g_czero = 1
  1396. }
  1397.  
  1398. public plugin_cfg()
  1399. {
  1400. // Plugin disabled?
  1401. if (!g_pluginenabled) return;
  1402.  
  1403. // Get configs dir
  1404. new cfgdir[32]
  1405. get_configsdir(cfgdir, charsmax(cfgdir))
  1406.  
  1407. // Execute config file (zombieplague.cfg)
  1408. server_cmd("exec %s/zombieplague.cfg", cfgdir)
  1409.  
  1410. // Prevent any more stuff from registering
  1411. g_arrays_created = false
  1412.  
  1413. // Save customization data
  1414. save_customization()
  1415.  
  1416. // Lighting task
  1417. set_task(5.0, "lighting_effects", _, _, _, "b")
  1418.  
  1419. // Cache CVARs after configs are loaded / call roundstart manually
  1420. set_task(0.5, "cache_cvars")
  1421. set_task(0.5, "event_round_start")
  1422. set_task(0.5, "logevent_round_start")
  1423. }
  1424.  
  1425. /*================================================================================
  1426. [Main Events]
  1427. =================================================================================*/
  1428.  
  1429. // Event Round Start
  1430. public event_round_start()
  1431. {
  1432. // Remove doors/lights?
  1433. set_task(0.1, "remove_stuff")
  1434.  
  1435. // New round starting
  1436. g_newround = true
  1437. g_endround = false
  1438. g_survround = false
  1439. g_nemround = false
  1440. g_swarmround = false
  1441. g_plagueround = false
  1442. g_modestarted = false
  1443.  
  1444. // Reset bought infection bombs counter
  1445. g_infbombcounter = 0
  1446. g_antidotecounter = 0
  1447. g_madnesscounter = 0
  1448.  
  1449. // Freezetime begins
  1450. g_freezetime = true
  1451.  
  1452. // Show welcome message and T-Virus notice
  1453. remove_task(TASK_WELCOMEMSG)
  1454. set_task(2.0, "welcome_msg", TASK_WELCOMEMSG)
  1455.  
  1456. // Set a new "Make Zombie Task"
  1457. remove_task(TASK_MAKEZOMBIE)
  1458. set_task(2.0 + get_pcvar_float(cvar_warmup), "make_zombie_task", TASK_MAKEZOMBIE)
  1459. }
  1460.  
  1461. // Log Event Round Start
  1462. public logevent_round_start()
  1463. {
  1464. // Freezetime ends
  1465. g_freezetime = false
  1466. }
  1467.  
  1468. // Log Event Round End
  1469. public logevent_round_end()
  1470. {
  1471. // Prevent this from getting called twice when restarting (bugfix)
  1472. static Float:lastendtime, Float:current_time
  1473. current_time = get_gametime()
  1474. if (current_time - lastendtime < 0.5) return;
  1475. lastendtime = current_time
  1476.  
  1477. // Temporarily save player stats?
  1478. if (get_pcvar_num(cvar_statssave))
  1479. {
  1480. static id, team
  1481. for (id = 1; id <= g_maxplayers; id++)
  1482. {
  1483. // Not connected
  1484. if (!g_isconnected[id])
  1485. continue;
  1486.  
  1487. team = fm_cs_get_user_team(id)
  1488.  
  1489. // Not playing
  1490. if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
  1491. continue;
  1492.  
  1493. save_stats(id)
  1494. }
  1495. }
  1496.  
  1497. // Round ended
  1498. g_endround = true
  1499.  
  1500. // Stop old tasks (if any)
  1501. remove_task(TASK_WELCOMEMSG)
  1502. remove_task(TASK_MAKEZOMBIE)
  1503.  
  1504. // Stop ambience sounds
  1505. if ((g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] && g_nemround) || (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] && g_survround) || (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] && g_swarmround) || (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] && g_plagueround) || (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] && !g_nemround && !g_survround && !g_swarmround && !g_plagueround))
  1506. {
  1507. remove_task(TASK_AMBIENCESOUNDS)
  1508. ambience_sound_stop()
  1509. }
  1510.  
  1511. // Show HUD notice, play win sound, update team scores...
  1512. static sound[64]
  1513. if (!fnGetZombies())
  1514. {
  1515. // Human team wins
  1516. set_hudmessage(0, 0, 200, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
  1517. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "WIN_HUMAN")
  1518.  
  1519. // Play win sound and increase score
  1520. ArrayGetString(sound_win_humans, random_num(0, ArraySize(sound_win_humans) - 1), sound, charsmax(sound))
  1521. PlaySound(sound)
  1522. g_scorehumans++
  1523.  
  1524. // Round end forward
  1525. ExecuteForward(g_fwRoundEnd, g_fwDummyResult, ZP_TEAM_HUMAN);
  1526. }
  1527. else if (!fnGetHumans())
  1528. {
  1529. // Zombie team wins
  1530. set_hudmessage(200, 0, 0, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
  1531. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "WIN_ZOMBIE")
  1532.  
  1533. // Play win sound and increase score
  1534. ArrayGetString(sound_win_zombies, random_num(0, ArraySize(sound_win_zombies) - 1), sound, charsmax(sound))
  1535. PlaySound(sound)
  1536. g_scorezombies++
  1537.  
  1538. // Round end forward
  1539. ExecuteForward(g_fwRoundEnd, g_fwDummyResult, ZP_TEAM_ZOMBIE);
  1540. }
  1541. else
  1542. {
  1543. // No one wins
  1544. set_hudmessage(0, 200, 0, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
  1545. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "WIN_NO_ONE")
  1546.  
  1547. // Play win sound
  1548. ArrayGetString(sound_win_no_one, random_num(0, ArraySize(sound_win_no_one) - 1), sound, charsmax(sound))
  1549. PlaySound(sound)
  1550.  
  1551. // Round end forward
  1552. ExecuteForward(g_fwRoundEnd, g_fwDummyResult, ZP_TEAM_NO_ONE);
  1553. }
  1554.  
  1555. // Balance the teams
  1556. balance_teams()
  1557. }
  1558.  
  1559. // Event Map Ended
  1560. public event_intermission()
  1561. {
  1562. // Remove ambience sounds task
  1563. remove_task(TASK_AMBIENCESOUNDS)
  1564. }
  1565.  
  1566. // BP Ammo update
  1567. public event_ammo_x(id)
  1568. {
  1569. // Humans only
  1570. if (g_zombie[id])
  1571. return;
  1572.  
  1573. // Get ammo type
  1574. static type
  1575. type = read_data(1)
  1576.  
  1577. // Unknown ammo type
  1578. if (type >= sizeof AMMOWEAPON)
  1579. return;
  1580.  
  1581. // Get weapon's id
  1582. static weapon
  1583. weapon = AMMOWEAPON[type]
  1584.  
  1585. // Primary and secondary only
  1586. if (MAXBPAMMO[weapon] <= 2)
  1587. return;
  1588.  
  1589. // Get ammo amount
  1590. static amount
  1591. amount = read_data(2)
  1592.  
  1593. // Unlimited BP Ammo?
  1594. if (g_survivor[id] ? get_pcvar_num(cvar_survinfammo) : get_pcvar_num(cvar_infammo))
  1595. {
  1596. if (amount < MAXBPAMMO[weapon])
  1597. {
  1598. // The BP Ammo refill code causes the engine to send a message, but we
  1599. // can't have that in this forward or we risk getting some recursion bugs.
  1600. // For more info see: https://bugs.alliedmods.net/show_bug.cgi?id=3664
  1601. static args[1]
  1602. args[0] = weapon
  1603. set_task(0.1, "refill_bpammo", id, args, sizeof args)
  1604. }
  1605. }
  1606. // Bots automatically buy ammo when needed
  1607. else if (g_isbot[id] && amount <= BUYAMMO[weapon])
  1608. {
  1609. // Task needed for the same reason as above
  1610. set_task(0.1, "clcmd_buyammo", id)
  1611. }
  1612. }
  1613.  
  1614. /*================================================================================
  1615. [Main Forwards]
  1616. =================================================================================*/
  1617.  
  1618. // Entity Spawn Forward
  1619. public fw_Spawn(entity)
  1620. {
  1621. // Invalid entity
  1622. if (!pev_valid(entity)) return FMRES_IGNORED;
  1623.  
  1624. // Get classname
  1625. new classname[32], objective[32], size = ArraySize(g_objective_ents)
  1626. pev(entity, pev_classname, classname, charsmax(classname))
  1627.  
  1628. // Check whether it needs to be removed
  1629. for (new i = 0; i < size; i++)
  1630. {
  1631. ArrayGetString(g_objective_ents, i, objective, charsmax(objective))
  1632.  
  1633. if (equal(classname, objective))
  1634. {
  1635. engfunc(EngFunc_RemoveEntity, entity)
  1636. return FMRES_SUPERCEDE;
  1637. }
  1638. }
  1639.  
  1640. return FMRES_IGNORED;
  1641. }
  1642.  
  1643. // Sound Precache Forward
  1644. public fw_PrecacheSound(const sound[])
  1645. {
  1646. // Block all those unneeeded hostage sounds
  1647. if (equal(sound, "hostage", 7))
  1648. return FMRES_SUPERCEDE;
  1649.  
  1650. return FMRES_IGNORED;
  1651. }
  1652.  
  1653. // Ham Player Spawn Post Forward
  1654. public fw_PlayerSpawn_Post(id)
  1655. {
  1656. // Not alive or didn't join a team yet
  1657. if (!is_user_alive(id) || !fm_cs_get_user_team(id))
  1658. return;
  1659.  
  1660. // Player spawned
  1661. g_isalive[id] = true
  1662.  
  1663. // Remove previous tasks
  1664. remove_task(id+TASK_SPAWN)
  1665. remove_task(id+TASK_MODEL)
  1666. remove_task(id+TASK_BLOOD)
  1667. remove_task(id+TASK_AURA)
  1668. remove_task(id+TASK_BURN)
  1669. remove_task(id+TASK_CHARGE)
  1670. remove_task(id+TASK_FLASH)
  1671. remove_task(id+TASK_NVISION)
  1672.  
  1673. // Spawn at a random location?
  1674. if (get_pcvar_num(cvar_randspawn)) do_random_spawn(id)
  1675.  
  1676. // Hide money?
  1677. if (get_pcvar_num(cvar_removemoney))
  1678. set_task(0.4, "task_hide_money", id+TASK_SPAWN)
  1679.  
  1680. // Respawn player if he dies because of a worldspawn kill?
  1681. if (get_pcvar_num(cvar_respawnworldspawnkill))
  1682. set_task(2.0, "respawn_player_task", id+TASK_SPAWN)
  1683.  
  1684. // Spawn as zombie?
  1685. if (g_respawn_as_zombie[id] && !g_newround)
  1686. {
  1687. reset_vars(id, 0) // reset player vars
  1688. zombieme(id, 0, 0, 0, 0) // make him zombie right away
  1689. return;
  1690. }
  1691.  
  1692. // Reset player vars
  1693. reset_vars(id, 0)
  1694.  
  1695. // Show custom buy menu?
  1696. if (get_pcvar_num(cvar_buycustom))
  1697. set_task(0.2, "show_menu_buy1", id+TASK_SPAWN)
  1698.  
  1699. // Set health and gravity
  1700. fm_set_user_health(id, get_pcvar_num(cvar_humanhp))
  1701. set_pev(id, pev_gravity, get_pcvar_float(cvar_humangravity))
  1702.  
  1703. // Switch to CT if spawning mid-round
  1704. if (!g_newround && fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
  1705. {
  1706. remove_task(id+TASK_TEAM)
  1707. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  1708. fm_user_team_update(id)
  1709. }
  1710.  
  1711. // Custom models stuff
  1712. static currentmodel[32], tempmodel[32], already_has_model, i, iRand, size
  1713. already_has_model = false
  1714.  
  1715. if (g_handle_models_on_separate_ent)
  1716. {
  1717. // Set the right model
  1718. if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
  1719. {
  1720. iRand = random_num(0, ArraySize(model_admin_human) - 1)
  1721. ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  1722. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
  1723. }
  1724. else
  1725. {
  1726. iRand = random_num(0, ArraySize(model_human) - 1)
  1727. ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  1728. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
  1729. }
  1730.  
  1731. // Set model on player model entity
  1732. fm_set_playermodel_ent(id)
  1733.  
  1734. // Remove glow on player model entity
  1735. fm_set_rendering(g_ent_playermodel[id])
  1736. }
  1737. else
  1738. {
  1739. // Get current model for comparing it with the current one
  1740. fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
  1741.  
  1742. // Set the right model, after checking that we don't already have it
  1743. if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
  1744. {
  1745. size = ArraySize(model_admin_human)
  1746. for (i = 0; i < size; i++)
  1747. {
  1748. ArrayGetString(model_admin_human, i, tempmodel, charsmax(tempmodel))
  1749. if (equal(currentmodel, tempmodel)) already_has_model = true
  1750. }
  1751.  
  1752. if (!already_has_model)
  1753. {
  1754. iRand = random_num(0, size - 1)
  1755. ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  1756. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
  1757. }
  1758. }
  1759. else
  1760. {
  1761. size = ArraySize(model_human)
  1762. for (i = 0; i < size; i++)
  1763. {
  1764. ArrayGetString(model_human, i, tempmodel, charsmax(tempmodel))
  1765. if (equal(currentmodel, tempmodel)) already_has_model = true
  1766. }
  1767.  
  1768. if (!already_has_model)
  1769. {
  1770. iRand = random_num(0, size - 1)
  1771. ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  1772. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
  1773. }
  1774. }
  1775.  
  1776. // Need to change the model?
  1777. if (!already_has_model)
  1778. {
  1779. // An additional delay is offset at round start
  1780. // since SVC_BAD is more likely to be triggered there
  1781. if (g_newround)
  1782. set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
  1783. else
  1784. fm_user_model_update(id+TASK_MODEL)
  1785. }
  1786.  
  1787. // Remove glow
  1788. fm_set_rendering(id)
  1789. }
  1790.  
  1791. // Bots stuff
  1792. if (g_isbot[id])
  1793. {
  1794. // Turn off NVG for bots
  1795. cs_set_user_nvg(id, 0)
  1796.  
  1797. // Automatically buy extra items/weapons after first zombie is chosen
  1798. if (get_pcvar_num(cvar_extraitems))
  1799. {
  1800. if (g_newround) set_task(10.0 + get_pcvar_float(cvar_warmup), "bot_buy_extras", id+TASK_SPAWN)
  1801. else set_task(10.0, "bot_buy_extras", id+TASK_SPAWN)
  1802. }
  1803. }
  1804.  
  1805. // Enable spawn protection for humans spawning mid-round
  1806. if (!g_newround && get_pcvar_float(cvar_spawnprotection) > 0.0)
  1807. {
  1808. // Do not take damage
  1809. g_nodamage[id] = true
  1810.  
  1811. // Make temporarily invisible
  1812. set_pev(id, pev_effects, pev(id, pev_effects) | EF_NODRAW)
  1813.  
  1814. // Set task to remove it
  1815. set_task(get_pcvar_float(cvar_spawnprotection), "remove_spawn_protection", id+TASK_SPAWN)
  1816. }
  1817.  
  1818. // Set the flashlight charge task to update battery status
  1819. if (g_cached_customflash)
  1820. set_task(1.0, "flashlight_charge", id+TASK_CHARGE, _, _, "b")
  1821.  
  1822. // Replace weapon models (bugfix)
  1823. static weapon_ent
  1824. weapon_ent = fm_cs_get_current_weapon_ent(id)
  1825. if (pev_valid(weapon_ent)) replace_weapon_models(id, cs_get_weapon_id(weapon_ent))
  1826.  
  1827. // Last Zombie Check
  1828. fnCheckLastZombie()
  1829. }
  1830.  
  1831. // Ham Player Killed Forward
  1832. public fw_PlayerKilled(victim, attacker, shouldgib)
  1833. {
  1834. // Player killed
  1835. g_isalive[victim] = false
  1836.  
  1837. // Enable dead players nightvision
  1838. set_task(0.1, "spec_nvision", victim)
  1839.  
  1840. // Disable nightvision when killed (bugfix)
  1841. if (get_pcvar_num(cvar_nvggive) == 0 && g_nvision[victim])
  1842. {
  1843. if (get_pcvar_num(cvar_customnvg)) remove_task(victim+TASK_NVISION)
  1844. else if (g_nvisionenabled[victim]) set_user_gnvision(victim, 0)
  1845. g_nvision[victim] = false
  1846. g_nvisionenabled[victim] = false
  1847. }
  1848.  
  1849. // Turn off nightvision when killed (bugfix)
  1850. if (get_pcvar_num(cvar_nvggive) == 2 && g_nvision[victim] && g_nvisionenabled[victim])
  1851. {
  1852. if (get_pcvar_num(cvar_customnvg)) remove_task(victim+TASK_NVISION)
  1853. else set_user_gnvision(victim, 0)
  1854. g_nvisionenabled[victim] = false
  1855. }
  1856.  
  1857. // Turn off custom flashlight when killed
  1858. if (g_cached_customflash)
  1859. {
  1860. // Turn it off
  1861. g_flashlight[victim] = false
  1862. g_flashbattery[victim] = 100
  1863.  
  1864. // Remove previous tasks
  1865. remove_task(victim+TASK_CHARGE)
  1866. remove_task(victim+TASK_FLASH)
  1867. }
  1868.  
  1869. // Stop bleeding/burning/aura when killed
  1870. if (g_zombie[victim])
  1871. {
  1872. remove_task(victim+TASK_BLOOD)
  1873. remove_task(victim+TASK_AURA)
  1874. remove_task(victim+TASK_BURN)
  1875. }
  1876.  
  1877. // Nemesis explodes!
  1878. if (g_nemesis[victim])
  1879. SetHamParamInteger(3, 2)
  1880.  
  1881. // Get deathmatch mode status and whether the player killed himself
  1882. static selfkill
  1883. selfkill = (victim == attacker || !is_user_valid_connected(attacker)) ? true : false
  1884.  
  1885. // Respawn if deathmatch is enabled
  1886. if (get_pcvar_num(cvar_deathmatch))
  1887. {
  1888. // Respawn on suicide?
  1889. if (selfkill && !get_pcvar_num(cvar_respawnonsuicide))
  1890. return;
  1891.  
  1892. // Respawn if only the last human is left?
  1893. if (!get_pcvar_num(cvar_respawnafterlast) && fnGetHumans() <= 1)
  1894. return;
  1895.  
  1896. // Respawn if human/zombie/nemesis/survivor?
  1897. if ((g_zombie[victim] && !g_nemesis[victim] && !get_pcvar_num(cvar_respawnzomb)) || (!g_zombie[victim] && !g_survivor[victim] && !get_pcvar_num(cvar_respawnhum)) || (g_nemesis[victim] && !get_pcvar_num(cvar_respawnnem)) || (g_survivor[victim] && !get_pcvar_num(cvar_respawnsurv)))
  1898. return;
  1899.  
  1900. // Respawn as zombie?
  1901. if (get_pcvar_num(cvar_deathmatch) == 2 || (get_pcvar_num(cvar_deathmatch) == 3 && random_num(0, 1)) || (get_pcvar_num(cvar_deathmatch) == 4 && fnGetZombies() < fnGetAlive()/2))
  1902. g_respawn_as_zombie[victim] = true
  1903.  
  1904. // Set the respawn task
  1905. set_task(get_pcvar_float(cvar_spawndelay), "respawn_player_task", victim+TASK_SPAWN)
  1906. }
  1907.  
  1908. // Killed by a non-player entity or self killed
  1909. if (selfkill) return;
  1910.  
  1911. // Ignore Nemesis/Survivor Frags?
  1912. if ((g_nemesis[attacker] && get_pcvar_num(cvar_nemignorefrags)) || (g_survivor[attacker] && get_pcvar_num(cvar_survignorefrags)))
  1913. RemoveFrags(attacker, victim)
  1914.  
  1915. // Zombie/nemesis killed human, reward ammo packs
  1916. if (g_zombie[attacker] && (!g_nemesis[attacker] || !get_pcvar_num(cvar_nemignoreammo)))
  1917. g_ammopacks[attacker] += get_pcvar_num(cvar_ammoinfect)
  1918.  
  1919. // Human killed zombie, add up the extra frags for kill
  1920. if (!g_zombie[attacker] && get_pcvar_num(cvar_fragskill) > 1)
  1921. UpdateFrags(attacker, victim, get_pcvar_num(cvar_fragskill) - 1, 0, 0)
  1922.  
  1923. // Zombie killed human, add up the extra frags for kill
  1924. if (g_zombie[attacker] && get_pcvar_num(cvar_fragsinfect) > 1)
  1925. UpdateFrags(attacker, victim, get_pcvar_num(cvar_fragsinfect) - 1, 0, 0)
  1926. }
  1927.  
  1928. // Ham Player Killed Post Forward
  1929. public fw_PlayerKilled_Post()
  1930. {
  1931. // Last Zombie Check
  1932. fnCheckLastZombie()
  1933. }
  1934.  
  1935. // Ham Take Damage Forward
  1936. public fw_TakeDamage(victim, inflictor, attacker, Float:damage, damage_type)
  1937. {
  1938. // Non-player damage or self damage
  1939. if (victim == attacker || !is_user_valid_connected(attacker))
  1940. return HAM_IGNORED;
  1941.  
  1942. // New round starting or round ended
  1943. if (g_newround || g_endround)
  1944. return HAM_SUPERCEDE;
  1945.  
  1946. // Victim shouldn't take damage or victim is frozen
  1947. if (g_nodamage[victim] || g_frozen[victim])
  1948. return HAM_SUPERCEDE;
  1949.  
  1950. // Prevent friendly fire
  1951. if (g_zombie[attacker] == g_zombie[victim])
  1952. return HAM_SUPERCEDE;
  1953.  
  1954. // Attacker is human...
  1955. if (!g_zombie[attacker])
  1956. {
  1957. // Armor multiplier for the final damage on normal zombies
  1958. if (!g_nemesis[victim])
  1959. {
  1960. damage *= get_pcvar_float(cvar_zombiearmor)
  1961. SetHamParamFloat(4, damage)
  1962. }
  1963.  
  1964. // Reward ammo packs
  1965. if (!g_survivor[attacker] || !get_pcvar_num(cvar_survignoreammo))
  1966. {
  1967. // Store damage dealt
  1968. g_damagedealt[attacker] += floatround(damage)
  1969.  
  1970. // Reward ammo packs for every [ammo damage] dealt
  1971. while (g_damagedealt[attacker] > get_pcvar_num(cvar_ammodamage))
  1972. {
  1973. g_ammopacks[attacker]++
  1974. g_damagedealt[attacker] -= get_pcvar_num(cvar_ammodamage)
  1975. }
  1976. }
  1977.  
  1978. return HAM_IGNORED;
  1979. }
  1980.  
  1981. // Attacker is zombie...
  1982.  
  1983. // Prevent infection/damage by HE grenade (bugfix)
  1984. if (damage_type & DMG_HEGRENADE)
  1985. return HAM_SUPERCEDE;
  1986.  
  1987. // Nemesis?
  1988. if (g_nemesis[attacker])
  1989. {
  1990. // Ignore nemesis damage override if damage comes from a 3rd party entity
  1991. // (to prevent this from affecting a sub-plugin's rockets e.g.)
  1992. if (inflictor == attacker)
  1993. {
  1994. // Set nemesis damage
  1995. SetHamParamFloat(4, get_pcvar_float(cvar_nemdamage))
  1996. }
  1997.  
  1998. return HAM_IGNORED;
  1999. }
  2000.  
  2001. // Last human or not an infection round
  2002. if (g_survround || g_nemround || g_swarmround || g_plagueround || fnGetHumans() == 1)
  2003. return HAM_IGNORED; // human is killed
  2004.  
  2005. // Does human armor need to be reduced before infecting?
  2006. if (get_pcvar_num(cvar_humanarmor))
  2007. {
  2008. // Get victim armor
  2009. static Float:armor
  2010. pev(victim, pev_armorvalue, armor)
  2011.  
  2012. // Block the attack if he has some
  2013. if (armor > 0.0)
  2014. {
  2015. emit_sound(victim, CHAN_BODY, sound_armorhit, 1.0, ATTN_NORM, 0, PITCH_NORM)
  2016. set_pev(victim, pev_armorvalue, floatmax(0.0, armor - damage))
  2017. return HAM_SUPERCEDE;
  2018. }
  2019. }
  2020.  
  2021. // Infection allowed
  2022. zombieme(victim, attacker, 0, 0, 1) // turn into zombie
  2023. return HAM_SUPERCEDE;
  2024. }
  2025.  
  2026. // Ham Take Damage Post Forward
  2027. public fw_TakeDamage_Post(victim)
  2028. {
  2029. // --- Check if victim should be Pain Shock Free ---
  2030.  
  2031. // Check if proper CVARs are enabled
  2032. if (g_zombie[victim])
  2033. {
  2034. if (g_nemesis[victim])
  2035. {
  2036. if (!get_pcvar_num(cvar_nempainfree)) return;
  2037. }
  2038. else
  2039. {
  2040. switch (get_pcvar_num(cvar_zombiepainfree))
  2041. {
  2042. case 0: return;
  2043. case 2: if (!g_lastzombie[victim]) return;
  2044. }
  2045. }
  2046. }
  2047. else
  2048. {
  2049. if (g_survivor[victim])
  2050. {
  2051. if (!get_pcvar_num(cvar_survpainfree)) return;
  2052. }
  2053. else return;
  2054. }
  2055.  
  2056. // Set pain shock free offset
  2057. set_pdata_float(victim, OFFSET_PAINSHOCK, 1.0, OFFSET_LINUX)
  2058. }
  2059.  
  2060. // Ham Trace Attack Forward
  2061. public fw_TraceAttack(victim, attacker, Float:damage, Float:direction[3], tracehandle, damage_type)
  2062. {
  2063. // Non-player damage or self damage
  2064. if (victim == attacker || !is_user_valid_connected(attacker))
  2065. return HAM_IGNORED;
  2066.  
  2067. // New round starting or round ended
  2068. if (g_newround || g_endround)
  2069. return HAM_SUPERCEDE;
  2070.  
  2071. // Victim shouldn't take damage or victim is frozen
  2072. if (g_nodamage[victim] || g_frozen[victim])
  2073. return HAM_SUPERCEDE;
  2074.  
  2075. // Prevent friendly fire
  2076. if (g_zombie[attacker] == g_zombie[victim])
  2077. return HAM_SUPERCEDE;
  2078.  
  2079. // Victim isn't a zombie or not bullet damage, nothing else to do here
  2080. if (!g_zombie[victim] || !(damage_type & DMG_BULLET))
  2081. return HAM_IGNORED;
  2082.  
  2083. // If zombie hitzones are enabled, check whether we hit an allowed one
  2084. if (get_pcvar_num(cvar_hitzones) && !g_nemesis[victim] && !(get_pcvar_num(cvar_hitzones) & (1<<get_tr2(tracehandle, TR_iHitgroup))))
  2085. return HAM_SUPERCEDE;
  2086.  
  2087. // Knockback disabled, nothing else to do here
  2088. if (!get_pcvar_num(cvar_knockback))
  2089. return HAM_IGNORED;
  2090.  
  2091. // Nemesis knockback disabled, nothing else to do here
  2092. if (g_nemesis[victim] && get_pcvar_float(cvar_nemknockback) == 0.0)
  2093. return HAM_IGNORED;
  2094.  
  2095. // Get whether the victim is in a crouch state
  2096. static ducking
  2097. ducking = pev(victim, pev_flags) & (FL_DUCKING | FL_ONGROUND) == (FL_DUCKING | FL_ONGROUND)
  2098.  
  2099. // Zombie knockback when ducking disabled
  2100. if (ducking && get_pcvar_float(cvar_knockbackducking) == 0.0)
  2101. return HAM_IGNORED;
  2102.  
  2103. // Get distance between players
  2104. static origin1[3], origin2[3]
  2105. get_user_origin(victim, origin1)
  2106. get_user_origin(attacker, origin2)
  2107.  
  2108. // Max distance exceeded
  2109. if (get_distance(origin1, origin2) > get_pcvar_num(cvar_knockbackdist))
  2110. return HAM_IGNORED;
  2111.  
  2112. // Get victim's velocity
  2113. static Float:velocity[3]
  2114. pev(victim, pev_velocity, velocity)
  2115.  
  2116. // Use damage on knockback calculation
  2117. if (get_pcvar_num(cvar_knockbackdamage))
  2118. xs_vec_mul_scalar(direction, damage, direction)
  2119.  
  2120. // Use weapon power on knockback calculation
  2121. if (get_pcvar_num(cvar_knockbackpower) && kb_weapon_power[g_currentweapon[attacker]] > 0.0)
  2122. xs_vec_mul_scalar(direction, kb_weapon_power[g_currentweapon[attacker]], direction)
  2123.  
  2124. // Apply ducking knockback multiplier
  2125. if (ducking)
  2126. xs_vec_mul_scalar(direction, get_pcvar_float(cvar_knockbackducking), direction)
  2127.  
  2128. // Apply zombie class/nemesis knockback multiplier
  2129. if (g_nemesis[victim])
  2130. xs_vec_mul_scalar(direction, get_pcvar_float(cvar_nemknockback), direction)
  2131. else
  2132. xs_vec_mul_scalar(direction, g_zombie_knockback[victim], direction)
  2133.  
  2134. // Add up the new vector
  2135. xs_vec_add(velocity, direction, direction)
  2136.  
  2137. // Should knockback also affect vertical velocity?
  2138. if (!get_pcvar_num(cvar_knockbackzvel))
  2139. direction[2] = velocity[2]
  2140.  
  2141. // Set the knockback'd victim's velocity
  2142. set_pev(victim, pev_velocity, direction)
  2143.  
  2144. return HAM_IGNORED;
  2145. }
  2146.  
  2147. // Ham Use Stationary Gun Forward
  2148. public fw_UseStationary(entity, caller, activator, use_type)
  2149. {
  2150. // Prevent zombies from using stationary guns
  2151. if (use_type == USE_USING && is_user_valid_connected(caller) && g_zombie[caller])
  2152. return HAM_SUPERCEDE;
  2153.  
  2154. return HAM_IGNORED;
  2155. }
  2156.  
  2157. // Ham Use Stationary Gun Post Forward
  2158. public fw_UseStationary_Post(entity, caller, activator, use_type)
  2159. {
  2160. // Someone stopped using a stationary gun
  2161. if (use_type == USE_STOPPED && is_user_valid_connected(caller))
  2162. replace_weapon_models(caller, g_currentweapon[caller]) // replace weapon models (bugfix)
  2163. }
  2164.  
  2165. // Ham Use Pushable Forward
  2166. public fw_UsePushable()
  2167. {
  2168. // Prevent speed bug with pushables?
  2169. if (get_pcvar_num(cvar_blockpushables))
  2170. return HAM_SUPERCEDE;
  2171.  
  2172. return HAM_IGNORED;
  2173. }
  2174.  
  2175. // Ham Weapon Touch Forward
  2176. public fw_TouchWeapon(weapon, id)
  2177. {
  2178. // Not a player
  2179. if (!is_user_valid_connected(id))
  2180. return HAM_IGNORED;
  2181.  
  2182. // Dont pickup weapons if zombie or survivor (+PODBot MM fix)
  2183. if (g_zombie[id] || (g_survivor[id] && !g_isbot[id]))
  2184. return HAM_SUPERCEDE;
  2185.  
  2186. return HAM_IGNORED;
  2187. }
  2188.  
  2189. // Ham Weapon Pickup Forward
  2190. public fw_AddPlayerItem(id, weapon_ent)
  2191. {
  2192. // HACK: Retrieve our custom extra ammo from the weapon
  2193. static extra_ammo
  2194. extra_ammo = pev(weapon_ent, PEV_ADDITIONAL_AMMO)
  2195.  
  2196. // If present
  2197. if (extra_ammo)
  2198. {
  2199. // Get weapon's id
  2200. static weaponid
  2201. weaponid = cs_get_weapon_id(weapon_ent)
  2202.  
  2203. // Add to player's bpammo
  2204. ExecuteHamB(Ham_GiveAmmo, id, extra_ammo, AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
  2205. set_pev(weapon_ent, PEV_ADDITIONAL_AMMO, 0)
  2206. }
  2207. }
  2208.  
  2209. // Ham Weapon Deploy Forward
  2210. public fw_Item_Deploy_Post(weapon_ent)
  2211. {
  2212. // Get weapon's owner
  2213. static owner
  2214. owner = fm_cs_get_weapon_ent_owner(weapon_ent)
  2215.  
  2216. // Get weapon's id
  2217. static weaponid
  2218. weaponid = cs_get_weapon_id(weapon_ent)
  2219.  
  2220. // Store current weapon's id for reference
  2221. g_currentweapon[owner] = weaponid
  2222.  
  2223. // Replace weapon models with custom ones
  2224. replace_weapon_models(owner, weaponid)
  2225.  
  2226. // Zombie not holding an allowed weapon for some reason
  2227. if (g_zombie[owner] && !((1<<weaponid) & ZOMBIE_ALLOWED_WEAPONS_BITSUM))
  2228. {
  2229. // Switch to knife
  2230. g_currentweapon[owner] = CSW_KNIFE
  2231. engclient_cmd(owner, "weapon_knife")
  2232. }
  2233. }
  2234.  
  2235. // WeaponMod bugfix
  2236. //forward wpn_gi_reset_weapon(id);
  2237. public wpn_gi_reset_weapon(id)
  2238. {
  2239. // Replace knife model
  2240. replace_weapon_models(id, CSW_KNIFE)
  2241. }
  2242.  
  2243. // Client joins the game
  2244. public client_putinserver(id)
  2245. {
  2246. // Plugin disabled?
  2247. if (!g_pluginenabled) return;
  2248.  
  2249. // Player joined
  2250. g_isconnected[id] = true
  2251.  
  2252. // Cache player's name
  2253. get_user_name(id, g_playername[id], charsmax(g_playername[]))
  2254.  
  2255. // Initialize player vars
  2256. reset_vars(id, 1)
  2257.  
  2258. // Load player stats?
  2259. if (get_pcvar_num(cvar_statssave)) load_stats(id)
  2260.  
  2261. // Set some tasks for humans only
  2262. if (!is_user_bot(id))
  2263. {
  2264. // Set the custom HUD display task
  2265. set_task(1.0, "ShowHUD", id+TASK_SHOWHUD, _, _, "b")
  2266.  
  2267. // Disable minmodels for clients to see zombies properly
  2268. //set_task(5.0, "disable_minmodels", id)
  2269. }
  2270. else
  2271. {
  2272. // Set bot flag
  2273. g_isbot[id] = true
  2274.  
  2275. // CZ bots seem to use a different "classtype" for player entities
  2276. // (or something like that) which needs to be hooked separately
  2277. if (!g_hamczbots && cvar_botquota)
  2278. {
  2279. // Set a task to let the private data initialize
  2280. set_task(0.1, "register_ham_czbots", id)
  2281. }
  2282. }
  2283. }
  2284.  
  2285. // Client leaving
  2286. public fw_ClientDisconnect(id)
  2287. {
  2288. // Check that we still have both humans and zombies to keep the round going
  2289. if (g_isalive[id]) check_round(id)
  2290.  
  2291. // Temporarily save player stats?
  2292. if (get_pcvar_num(cvar_statssave)) save_stats(id)
  2293.  
  2294. // Remove previous tasks
  2295. remove_task(id+TASK_TEAM)
  2296. remove_task(id+TASK_MODEL)
  2297. remove_task(id+TASK_FLASH)
  2298. remove_task(id+TASK_CHARGE)
  2299. remove_task(id+TASK_SPAWN)
  2300. remove_task(id+TASK_BLOOD)
  2301. remove_task(id+TASK_AURA)
  2302. remove_task(id+TASK_BURN)
  2303. remove_task(id+TASK_NVISION)
  2304. remove_task(id+TASK_SHOWHUD)
  2305.  
  2306. if (g_handle_models_on_separate_ent)
  2307. {
  2308. // Remove custom model entities
  2309. fm_remove_model_ents(id)
  2310. }
  2311.  
  2312. // Player left, clear cached flags
  2313. g_isconnected[id] = false
  2314. g_isbot[id] = false
  2315. g_isalive[id] = false
  2316. }
  2317.  
  2318. // Client left
  2319. public fw_ClientDisconnect_Post()
  2320. {
  2321. // Last Zombie Check
  2322. fnCheckLastZombie()
  2323. }
  2324.  
  2325. // Client Kill Forward
  2326. public fw_ClientKill()
  2327. {
  2328. // Prevent players from killing themselves?
  2329. if (get_pcvar_num(cvar_blocksuicide))
  2330. return FMRES_SUPERCEDE;
  2331.  
  2332. return FMRES_IGNORED;
  2333. }
  2334.  
  2335. // Emit Sound Forward
  2336. public fw_EmitSound(id, channel, const sample[], Float:volume, Float:attn, flags, pitch)
  2337. {
  2338. // Block all those unneeeded hostage sounds
  2339. if (sample[0] == 'h' && sample[1] == 'o' && sample[2] == 's' && sample[3] == 't' && sample[4] == 'a' && sample[5] == 'g' && sample[6] == 'e')
  2340. return FMRES_SUPERCEDE;
  2341.  
  2342. // Replace these next sounds for zombies only
  2343. if (!is_user_valid_connected(id) || !g_zombie[id])
  2344. return FMRES_IGNORED;
  2345.  
  2346. static sound[64]
  2347.  
  2348. // Zombie being hit
  2349. if (sample[7] == 'b' && sample[8] == 'h' && sample[9] == 'i' && sample[10] == 't')
  2350. {
  2351. if (g_nemesis[id])
  2352. {
  2353. ArrayGetString(nemesis_pain, random_num(0, ArraySize(nemesis_pain) - 1), sound, charsmax(sound))
  2354. emit_sound(id, channel, sound, volume, attn, flags, pitch)
  2355. }
  2356. else
  2357. {
  2358. ArrayGetString(zombie_pain, random_num(0, ArraySize(zombie_pain) - 1), sound, charsmax(sound))
  2359. emit_sound(id, channel, sound, volume, attn, flags, pitch)
  2360. }
  2361. return FMRES_SUPERCEDE;
  2362. }
  2363.  
  2364. // Zombie attacks with knife
  2365. if (sample[8] == 'k' && sample[9] == 'n' && sample[10] == 'i')
  2366. {
  2367. if (sample[14] == 's' && sample[15] == 'l' && sample[16] == 'a') // slash
  2368. {
  2369. ArrayGetString(zombie_miss_slash, random_num(0, ArraySize(zombie_miss_slash) - 1), sound, charsmax(sound))
  2370. emit_sound(id, channel, sound, volume, attn, flags, pitch)
  2371. return FMRES_SUPERCEDE;
  2372. }
  2373. if (sample[14] == 'h' && sample[15] == 'i' && sample[16] == 't') // hit
  2374. {
  2375. if (sample[17] == 'w') // wall
  2376. {
  2377. ArrayGetString(zombie_miss_wall, random_num(0, ArraySize(zombie_miss_wall) - 1), sound, charsmax(sound))
  2378. emit_sound(id, channel, sound, volume, attn, flags, pitch)
  2379. return FMRES_SUPERCEDE;
  2380. }
  2381. else
  2382. {
  2383. ArrayGetString(zombie_hit_normal, random_num(0, ArraySize(zombie_hit_normal) - 1), sound, charsmax(sound))
  2384. emit_sound(id, channel, sound, volume, attn, flags, pitch)
  2385. return FMRES_SUPERCEDE;
  2386. }
  2387. }
  2388. if (sample[14] == 's' && sample[15] == 't' && sample[16] == 'a') // stab
  2389. {
  2390. ArrayGetString(zombie_hit_stab, random_num(0, ArraySize(zombie_hit_stab) - 1), sound, charsmax(sound))
  2391. emit_sound(id, channel, sound, volume, attn, flags, pitch)
  2392. return FMRES_SUPERCEDE;
  2393. }
  2394. }
  2395.  
  2396. // Zombie dies
  2397. if (sample[7] == 'd' && ((sample[8] == 'i' && sample[9] == 'e') || (sample[8] == 'e' && sample[9] == 'a')))
  2398. {
  2399. ArrayGetString(zombie_die, random_num(0, ArraySize(zombie_die) - 1), sound, charsmax(sound))
  2400. emit_sound(id, channel, sound, volume, attn, flags, pitch)
  2401. return FMRES_SUPERCEDE;
  2402. }
  2403.  
  2404. // Zombie falls off
  2405. if (sample[10] == 'f' && sample[11] == 'a' && sample[12] == 'l' && sample[13] == 'l')
  2406. {
  2407. ArrayGetString(zombie_fall, random_num(0, ArraySize(zombie_fall) - 1), sound, charsmax(sound))
  2408. emit_sound(id, channel, sound, volume, attn, flags, pitch)
  2409. return FMRES_SUPERCEDE;
  2410. }
  2411.  
  2412. return FMRES_IGNORED;
  2413. }
  2414.  
  2415. // Forward Set ClientKey Value -prevent CS from changing player models-
  2416. public fw_SetClientKeyValue(id, const infobuffer[], const key[])
  2417. {
  2418. // Block CS model changes
  2419. if (key[0] == 'm' && key[1] == 'o' && key[2] == 'd' && key[3] == 'e' && key[4] == 'l')
  2420. return FMRES_SUPERCEDE;
  2421.  
  2422. return FMRES_IGNORED;
  2423. }
  2424.  
  2425. // Forward Client User Info Changed -prevent players from changing models-
  2426. public fw_ClientUserInfoChanged(id)
  2427. {
  2428. // Cache player's name
  2429. get_user_name(id, g_playername[id], charsmax(g_playername[]))
  2430.  
  2431. if (!g_handle_models_on_separate_ent)
  2432. {
  2433. // Get current model
  2434. static currentmodel[32]
  2435. fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
  2436.  
  2437. // If they're different, set model again
  2438. if (!equal(currentmodel, g_playermodel[id]) && !task_exists(id+TASK_MODEL))
  2439. fm_cs_set_user_model(id+TASK_MODEL)
  2440. }
  2441. }
  2442.  
  2443. // Forward Get Game Description
  2444. public fw_GetGameDescription()
  2445. {
  2446. // Return the mod name so it can be easily identified
  2447. forward_return(FMV_STRING, g_modname)
  2448.  
  2449. return FMRES_SUPERCEDE;
  2450. }
  2451.  
  2452. // Forward Set Model
  2453. public fw_SetModel(entity, const model[])
  2454. {
  2455. // We don't care
  2456. if (strlen(model) < 8)
  2457. return;
  2458.  
  2459. // Remove weapons?
  2460. if (get_pcvar_float(cvar_removedropped) > 0.0)
  2461. {
  2462. // Get entity's classname
  2463. static classname[10]
  2464. pev(entity, pev_classname, classname, charsmax(classname))
  2465.  
  2466. // Check if it's a weapon box
  2467. if (equal(classname, "weaponbox"))
  2468. {
  2469. // They get automatically removed when thinking
  2470. set_pev(entity, pev_nextthink, get_gametime() + get_pcvar_float(cvar_removedropped))
  2471. return;
  2472. }
  2473. }
  2474.  
  2475. // Narrow down our matches a bit
  2476. if (model[7] != 'w' || model[8] != '_')
  2477. return;
  2478.  
  2479. // Get damage time of grenade
  2480. static Float:dmgtime
  2481. pev(entity, pev_dmgtime, dmgtime)
  2482.  
  2483. // Grenade not yet thrown
  2484. if (dmgtime == 0.0)
  2485. return;
  2486.  
  2487. // Get whether grenade's owner is a zombie
  2488. if (g_zombie[pev(entity, pev_owner)])
  2489. {
  2490. if (model[9] == 'h' && model[10] == 'e' && get_pcvar_num(cvar_extrainfbomb)) // Infection Bomb
  2491. {
  2492. // Give it a glow
  2493. fm_set_rendering(entity, kRenderFxGlowShell, 0, 200, 0, kRenderNormal, 16);
  2494.  
  2495. // And a colored trail
  2496. message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  2497. write_byte(TE_BEAMFOLLOW) // TE id
  2498. write_short(entity) // entity
  2499. write_short(g_trailSpr) // sprite
  2500. write_byte(10) // life
  2501. write_byte(10) // width
  2502. write_byte(0) // r
  2503. write_byte(200) // g
  2504. write_byte(0) // b
  2505. write_byte(200) // brightness
  2506. message_end()
  2507.  
  2508. // Set grenade type on the thrown grenade entity
  2509. set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_INFECTION)
  2510. }
  2511. }
  2512. else if (model[9] == 'h' && model[10] == 'e' && get_pcvar_num(cvar_firegrenades)) // Napalm Grenade
  2513. {
  2514. // Give it a glow
  2515. fm_set_rendering(entity, kRenderFxGlowShell, 200, 0, 0, kRenderNormal, 16);
  2516.  
  2517. // And a colored trail
  2518. message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  2519. write_byte(TE_BEAMFOLLOW) // TE id
  2520. write_short(entity) // entity
  2521. write_short(g_trailSpr) // sprite
  2522. write_byte(10) // life
  2523. write_byte(10) // width
  2524. write_byte(200) // r
  2525. write_byte(0) // g
  2526. write_byte(0) // b
  2527. write_byte(200) // brightness
  2528. message_end()
  2529.  
  2530. // Set grenade type on the thrown grenade entity
  2531. set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_NAPALM)
  2532. }
  2533. else if (model[9] == 'f' && model[10] == 'l' && get_pcvar_num(cvar_frostgrenades)) // Frost Grenade
  2534. {
  2535. // Give it a glow
  2536. fm_set_rendering(entity, kRenderFxGlowShell, 0, 100, 200, kRenderNormal, 16);
  2537.  
  2538. // And a colored trail
  2539. message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  2540. write_byte(TE_BEAMFOLLOW) // TE id
  2541. write_short(entity) // entity
  2542. write_short(g_trailSpr) // sprite
  2543. write_byte(10) // life
  2544. write_byte(10) // width
  2545. write_byte(0) // r
  2546. write_byte(100) // g
  2547. write_byte(200) // b
  2548. write_byte(200) // brightness
  2549. message_end()
  2550.  
  2551. // Set grenade type on the thrown grenade entity
  2552. set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_FROST)
  2553. }
  2554. else if (model[9] == 's' && model[10] == 'm' && get_pcvar_num(cvar_flaregrenades)) // Flare
  2555. {
  2556. // Build flare's color
  2557. static rgb[3]
  2558. switch (get_pcvar_num(cvar_flarecolor))
  2559. {
  2560. case 0: // white
  2561. {
  2562. rgb[0] = 255 // r
  2563. rgb[1] = 255 // g
  2564. rgb[2] = 255 // b
  2565. }
  2566. case 1: // red
  2567. {
  2568. rgb[0] = random_num(50,255) // r
  2569. rgb[1] = 0 // g
  2570. rgb[2] = 0 // b
  2571. }
  2572. case 2: // green
  2573. {
  2574. rgb[0] = 0 // r
  2575. rgb[1] = random_num(50,255) // g
  2576. rgb[2] = 0 // b
  2577. }
  2578. case 3: // blue
  2579. {
  2580. rgb[0] = 0 // r
  2581. rgb[1] = 0 // g
  2582. rgb[2] = random_num(50,255) // b
  2583. }
  2584. case 4: // random (all colors)
  2585. {
  2586. rgb[0] = random_num(50,200) // r
  2587. rgb[1] = random_num(50,200) // g
  2588. rgb[2] = random_num(50,200) // b
  2589. }
  2590. case 5: // random (r,g,b)
  2591. {
  2592. switch (random_num(1, 3))
  2593. {
  2594. case 1: // red
  2595. {
  2596. rgb[0] = random_num(50,255) // r
  2597. rgb[1] = 0 // g
  2598. rgb[2] = 0 // b
  2599. }
  2600. case 2: // green
  2601. {
  2602. rgb[0] = 0 // r
  2603. rgb[1] = random_num(50,255) // g
  2604. rgb[2] = 0 // b
  2605. }
  2606. case 3: // blue
  2607. {
  2608. rgb[0] = 0 // r
  2609. rgb[1] = 0 // g
  2610. rgb[2] = random_num(50,255) // b
  2611. }
  2612. }
  2613. }
  2614. }
  2615.  
  2616. // Give it a glow
  2617. fm_set_rendering(entity, kRenderFxGlowShell, rgb[0], rgb[1], rgb[2], kRenderNormal, 16);
  2618.  
  2619. // And a colored trail
  2620. message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  2621. write_byte(TE_BEAMFOLLOW) // TE id
  2622. write_short(entity) // entity
  2623. write_short(g_trailSpr) // sprite
  2624. write_byte(10) // life
  2625. write_byte(10) // width
  2626. write_byte(rgb[0]) // r
  2627. write_byte(rgb[1]) // g
  2628. write_byte(rgb[2]) // b
  2629. write_byte(200) // brightness
  2630. message_end()
  2631.  
  2632. // Set grenade type on the thrown grenade entity
  2633. set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_FLARE)
  2634.  
  2635. // Set flare color on the thrown grenade entity
  2636. set_pev(entity, PEV_FLARE_COLOR, rgb)
  2637. }
  2638. }
  2639.  
  2640. // Ham Grenade Think Forward
  2641. public fw_ThinkGrenade(entity)
  2642. {
  2643. // Invalid entity
  2644. if (!pev_valid(entity)) return HAM_IGNORED;
  2645.  
  2646. // Get damage time of grenade
  2647. static Float:dmgtime, Float:current_time
  2648. pev(entity, pev_dmgtime, dmgtime)
  2649. current_time = get_gametime()
  2650.  
  2651. // Check if it's time to go off
  2652. if (dmgtime > current_time)
  2653. return HAM_IGNORED;
  2654.  
  2655. // Check if it's one of our custom nades
  2656. switch (pev(entity, PEV_NADE_TYPE))
  2657. {
  2658. case NADE_TYPE_INFECTION: // Infection Bomb
  2659. {
  2660. infection_explode(entity)
  2661. return HAM_SUPERCEDE;
  2662. }
  2663. case NADE_TYPE_NAPALM: // Napalm Grenade
  2664. {
  2665. fire_explode(entity)
  2666. return HAM_SUPERCEDE;
  2667. }
  2668. case NADE_TYPE_FROST: // Frost Grenade
  2669. {
  2670. frost_explode(entity)
  2671. return HAM_SUPERCEDE;
  2672. }
  2673. case NADE_TYPE_FLARE: // Flare
  2674. {
  2675. // Get its duration
  2676. static duration
  2677. duration = pev(entity, PEV_FLARE_DURATION)
  2678.  
  2679. // Already went off, do lighting loop for the duration of PEV_FLARE_DURATION
  2680. if (duration > 0)
  2681. {
  2682. // Check whether this is the last loop
  2683. if (duration == 1)
  2684. {
  2685. // Get rid of the flare entity
  2686. engfunc(EngFunc_RemoveEntity, entity)
  2687. return HAM_SUPERCEDE;
  2688. }
  2689.  
  2690. // Light it up!
  2691. flare_lighting(entity, duration)
  2692.  
  2693. // Set time for next loop
  2694. set_pev(entity, PEV_FLARE_DURATION, --duration)
  2695. set_pev(entity, pev_dmgtime, current_time + 5.0)
  2696. }
  2697. // Light up when it's stopped on ground
  2698. else if ((pev(entity, pev_flags) & FL_ONGROUND) && fm_get_speed(entity) < 10)
  2699. {
  2700. // Flare sound
  2701. static sound[64]
  2702. ArrayGetString(grenade_flare, random_num(0, ArraySize(grenade_flare) - 1), sound, charsmax(sound))
  2703. emit_sound(entity, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  2704.  
  2705. // Set duration and start lightning loop on next think
  2706. set_pev(entity, PEV_FLARE_DURATION, 1 + get_pcvar_num(cvar_flareduration)/5)
  2707. set_pev(entity, pev_dmgtime, current_time + 0.1)
  2708. }
  2709. else
  2710. {
  2711. // Delay explosion until we hit ground
  2712. set_pev(entity, pev_dmgtime, current_time + 0.5)
  2713. }
  2714. }
  2715. }
  2716.  
  2717. return HAM_IGNORED;
  2718. }
  2719.  
  2720. // Forward CmdStart
  2721. public fw_CmdStart(id, handle)
  2722. {
  2723. // Not alive
  2724. if (!g_isalive[id])
  2725. return;
  2726.  
  2727. // This logic looks kinda weird, but it should work in theory...
  2728. // p = g_zombie[id], q = g_survivor[id], r = g_cached_customflash
  2729. // ¬(p v q v (¬p ^ r)) <==> ¬p ^ ¬q ^ (p v ¬r)
  2730. if (!g_zombie[id] && !g_survivor[id] && (g_zombie[id] || !g_cached_customflash))
  2731. return;
  2732.  
  2733. // Check if it's a flashlight impulse
  2734. if (get_uc(handle, UC_Impulse) != IMPULSE_FLASHLIGHT)
  2735. return;
  2736.  
  2737. // Block it I say!
  2738. set_uc(handle, UC_Impulse, 0)
  2739.  
  2740. // Should human's custom flashlight be turned on?
  2741. if (!g_zombie[id] && !g_survivor[id] && g_flashbattery[id] > 2 && get_gametime() - g_lastflashtime[id] > 1.2)
  2742. {
  2743. // Prevent calling flashlight too quickly (bugfix)
  2744. g_lastflashtime[id] = get_gametime()
  2745.  
  2746. // Toggle custom flashlight
  2747. g_flashlight[id] = !(g_flashlight[id])
  2748.  
  2749. // Play flashlight toggle sound
  2750. emit_sound(id, CHAN_ITEM, sound_flashlight, 1.0, ATTN_NORM, 0, PITCH_NORM)
  2751.  
  2752. // Update flashlight status on the HUD
  2753. message_begin(MSG_ONE, g_msgFlashlight, _, id)
  2754. write_byte(g_flashlight[id]) // toggle
  2755. write_byte(g_flashbattery[id]) // battery
  2756. message_end()
  2757.  
  2758. // Remove previous tasks
  2759. remove_task(id+TASK_CHARGE)
  2760. remove_task(id+TASK_FLASH)
  2761.  
  2762. // Set the flashlight charge task
  2763. set_task(1.0, "flashlight_charge", id+TASK_CHARGE, _, _, "b")
  2764.  
  2765. // Call our custom flashlight task if enabled
  2766. if (g_flashlight[id]) set_task(0.1, "set_user_flashlight", id+TASK_FLASH, _, _, "b")
  2767. }
  2768. }
  2769.  
  2770. // Forward Player PreThink
  2771. public fw_PlayerPreThink(id)
  2772. {
  2773. // Not alive
  2774. if (!g_isalive[id])
  2775. return;
  2776.  
  2777. // Silent footsteps for zombies?
  2778. if (g_cached_zombiesilent && g_zombie[id] && !g_nemesis[id])
  2779. set_pev(id, pev_flTimeStepSound, STEPTIME_SILENT)
  2780.  
  2781. // Set Player MaxSpeed
  2782. if (g_frozen[id])
  2783. {
  2784. set_pev(id, pev_velocity, Float:{0.0,0.0,0.0}) // stop motion
  2785. set_pev(id, pev_maxspeed, 1.0) // prevent from moving
  2786. return; // shouldn't leap while frozen
  2787. }
  2788. else if (g_freezetime)
  2789. {
  2790. return; // shouldn't leap while in freezetime
  2791. }
  2792. else
  2793. {
  2794. if (g_zombie[id])
  2795. {
  2796. if (g_nemesis[id])
  2797. set_pev(id, pev_maxspeed, g_cached_nemspd)
  2798. else
  2799. set_pev(id, pev_maxspeed, g_zombie_spd[id])
  2800. }
  2801. else
  2802. {
  2803. if (g_survivor[id])
  2804. set_pev(id, pev_maxspeed, g_cached_survspd)
  2805. else
  2806. set_pev(id, pev_maxspeed, g_cached_humanspd)
  2807. }
  2808. }
  2809.  
  2810. // --- Check if player should leap ---
  2811.  
  2812. // Check if proper CVARs are enabled and retrieve leap settings
  2813. static Float:cooldown, Float:current_time
  2814. if (g_zombie[id])
  2815. {
  2816. if (g_nemesis[id])
  2817. {
  2818. if (!g_cached_leapnemesis) return;
  2819. cooldown = g_cached_leapnemesiscooldown
  2820. }
  2821. else
  2822. {
  2823. switch (g_cached_leapzombies)
  2824. {
  2825. case 0: return;
  2826. case 2: if (!g_firstzombie[id]) return;
  2827. case 3: if (!g_lastzombie[id]) return;
  2828. }
  2829. cooldown = g_cached_leapzombiescooldown
  2830. }
  2831. }
  2832. else
  2833. {
  2834. if (g_survivor[id])
  2835. {
  2836. if (!g_cached_leapsurvivor) return;
  2837. cooldown = g_cached_leapsurvivorcooldown
  2838. }
  2839. else return;
  2840. }
  2841.  
  2842. current_time = get_gametime()
  2843.  
  2844. // Cooldown not over yet
  2845. if (current_time - g_lastleaptime[id] < cooldown)
  2846. return;
  2847.  
  2848. // Not doing a longjump (don't perform check for bots, they leap automatically)
  2849. if (!g_isbot[id] && !(pev(id, pev_button) & (IN_JUMP | IN_DUCK) == (IN_JUMP | IN_DUCK)))
  2850. return;
  2851.  
  2852. // Not on ground or not enough speed
  2853. if (!(pev(id, pev_flags) & FL_ONGROUND) || fm_get_speed(id) < 80)
  2854. return;
  2855.  
  2856. static Float:velocity[3]
  2857.  
  2858. // Make velocity vector
  2859. velocity_by_aim(id, g_survivor[id] ? get_pcvar_num(cvar_leapsurvivorforce) : g_nemesis[id] ? get_pcvar_num(cvar_leapnemesisforce) : get_pcvar_num(cvar_leapzombiesforce), velocity)
  2860.  
  2861. // Set custom height
  2862. velocity[2] = g_survivor[id] ? get_pcvar_float(cvar_leapsurvivorheight) : g_nemesis[id] ? get_pcvar_float(cvar_leapnemesisheight) : get_pcvar_float(cvar_leapzombiesheight)
  2863.  
  2864. // Apply the new velocity
  2865. set_pev(id, pev_velocity, velocity)
  2866.  
  2867. // Update last leap time
  2868. g_lastleaptime[id] = current_time
  2869. }
  2870.  
  2871. /*================================================================================
  2872. [Client Commands]
  2873. =================================================================================*/
  2874.  
  2875. // Say "/zpmenu"
  2876. public clcmd_saymenu(id)
  2877. {
  2878. show_menu_game(id) // show game menu
  2879. }
  2880.  
  2881. // Say "/unstuck"
  2882. public clcmd_sayunstuck(id)
  2883. {
  2884. menu_game(id, 3) // try to get unstuck
  2885. }
  2886.  
  2887. // Nightvision toggle
  2888. public clcmd_nightvision(id)
  2889. {
  2890. if (g_nvision[id])
  2891. {
  2892. // Enable-disable
  2893. g_nvisionenabled[id] = !(g_nvisionenabled[id])
  2894.  
  2895. // Custom nvg?
  2896. if (get_pcvar_num(cvar_customnvg))
  2897. {
  2898. remove_task(id+TASK_NVISION)
  2899. if (g_nvisionenabled[id]) set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
  2900. }
  2901. else
  2902. set_user_gnvision(id, g_nvisionenabled[id])
  2903. }
  2904.  
  2905. return PLUGIN_HANDLED;
  2906. }
  2907.  
  2908. // Weapon Drop
  2909. public clcmd_drop(id)
  2910. {
  2911. // Survivor should stick with its weapon
  2912. if (g_survivor[id])
  2913. return PLUGIN_HANDLED;
  2914.  
  2915. return PLUGIN_CONTINUE;
  2916. }
  2917.  
  2918. // Buy BP Ammo
  2919. public clcmd_buyammo(id)
  2920. {
  2921. // Not alive or infinite ammo setting enabled
  2922. if (!g_isalive[id] || get_pcvar_num(cvar_infammo))
  2923. return PLUGIN_HANDLED;
  2924.  
  2925. // Not human
  2926. if (g_zombie[id])
  2927. {
  2928. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_HUMAN_ONLY")
  2929. return PLUGIN_HANDLED;
  2930. }
  2931.  
  2932. // Not enough ammo packs
  2933. if (g_ammopacks[id] < 1)
  2934. {
  2935. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "NOT_ENOUGH_AMMO")
  2936. return PLUGIN_HANDLED;
  2937. }
  2938.  
  2939. // Get user weapons
  2940. static weapons[32], num, i, currentammo, weaponid, refilled
  2941. num = 0 // reset passed weapons count (bugfix)
  2942. refilled = false
  2943. get_user_weapons(id, weapons, num)
  2944.  
  2945. // Loop through them and give the right ammo type
  2946. for (i = 0; i < num; i++)
  2947. {
  2948. // Prevents re-indexing the array
  2949. weaponid = weapons[i]
  2950.  
  2951. // Primary and secondary only
  2952. if (MAXBPAMMO[weaponid] > 2)
  2953. {
  2954. // Get current ammo of the weapon
  2955. currentammo = cs_get_user_bpammo(id, weaponid)
  2956.  
  2957. // Give additional ammo
  2958. ExecuteHamB(Ham_GiveAmmo, id, BUYAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
  2959.  
  2960. // Check whether we actually refilled the weapon's ammo
  2961. if (cs_get_user_bpammo(id, weaponid) - currentammo > 0) refilled = true
  2962. }
  2963. }
  2964.  
  2965. // Weapons already have full ammo
  2966. if (!refilled) return PLUGIN_HANDLED;
  2967.  
  2968. // Deduce ammo packs, play clip purchase sound, and notify player
  2969. g_ammopacks[id]--
  2970. emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
  2971. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "AMMO_BOUGHT")
  2972.  
  2973. return PLUGIN_HANDLED;
  2974. }
  2975.  
  2976. // Block Team Change
  2977. public clcmd_changeteam(id)
  2978. {
  2979. static team
  2980. team = fm_cs_get_user_team(id)
  2981.  
  2982. // Unless it's a spectator joining the game
  2983. if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
  2984. return PLUGIN_CONTINUE;
  2985.  
  2986. // Pressing 'M' (chooseteam) ingame should show the main menu instead
  2987. show_menu_game(id)
  2988. return PLUGIN_HANDLED;
  2989. }
  2990.  
  2991. /*================================================================================
  2992. [Menus]
  2993. =================================================================================*/
  2994.  
  2995. // Game Menu
  2996. show_menu_game(id)
  2997. {
  2998. static menu[250], len, userflags
  2999. len = 0
  3000. userflags = get_user_flags(id)
  3001.  
  3002. // Title
  3003. len += formatex(menu[len], charsmax(menu) - len, "\y%s^n^n", g_modname)
  3004.  
  3005. // 1. Buy weapons
  3006. if (get_pcvar_num(cvar_buycustom))
  3007. len += formatex(menu[len], charsmax(menu) - len, "\r1.\w %L^n", id, "MENU_BUY")
  3008. else
  3009. len += formatex(menu[len], charsmax(menu) - len, "\d1. %L^n", id, "MENU_BUY")
  3010.  
  3011. // 2. Extra items
  3012. if (get_pcvar_num(cvar_extraitems) && g_isalive[id])
  3013. len += formatex(menu[len], charsmax(menu) - len, "\r2.\w %L^n", id, "MENU_EXTRABUY")
  3014. else
  3015. len += formatex(menu[len], charsmax(menu) - len, "\d2. %L^n", id, "MENU_EXTRABUY")
  3016.  
  3017. // 3. Zombie class
  3018. if (get_pcvar_num(cvar_zclasses))
  3019. len += formatex(menu[len], charsmax(menu) - len, "\r3.\w %L^n", id,"MENU_ZCLASS")
  3020. else
  3021. len += formatex(menu[len], charsmax(menu) - len, "\d3. %L^n", id,"MENU_ZCLASS")
  3022.  
  3023. // 4. Unstuck
  3024. if (g_isalive[id])
  3025. len += formatex(menu[len], charsmax(menu) - len, "\r4.\w %L^n", id, "MENU_UNSTUCK")
  3026. else
  3027. len += formatex(menu[len], charsmax(menu) - len, "\d4. %L^n", id, "MENU_UNSTUCK")
  3028.  
  3029. // 5. Help
  3030. len += formatex(menu[len], charsmax(menu) - len, "\r5.\w %L^n^n", id, "MENU_INFO")
  3031.  
  3032. // 6. Join spec
  3033. if (!g_isalive[id] || !get_pcvar_num(cvar_blocksuicide) || (userflags & g_access_flag[ACCESS_ADMIN_MENU]))
  3034. len += formatex(menu[len], charsmax(menu) - len, "\r6.\w %L^n^n", id, "MENU_SPECTATOR")
  3035. else
  3036. len += formatex(menu[len], charsmax(menu) - len, "\d6. %L^n^n", id, "MENU_SPECTATOR")
  3037.  
  3038. // 9. Admin menu
  3039. if (userflags & g_access_flag[ACCESS_ADMIN_MENU])
  3040. len += formatex(menu[len], charsmax(menu) - len, "\r9.\w %L", id, "MENU_ADMIN")
  3041. else
  3042. len += formatex(menu[len], charsmax(menu) - len, "\d9. %L", id, "MENU_ADMIN")
  3043.  
  3044. // 0. Exit
  3045. len += formatex(menu[len], charsmax(menu) - len, "^n^n\r0.\w %L", id, "MENU_EXIT")
  3046.  
  3047. show_menu(id, KEYSMENU, menu, -1, "Game Menu")
  3048. }
  3049.  
  3050. // Buy Menu 1
  3051. public show_menu_buy1(taskid)
  3052. {
  3053. // Get player's id
  3054. static id
  3055. (taskid > g_maxplayers) ? (id = ID_SPAWN) : (id = taskid);
  3056.  
  3057. // Zombies or survivors get no guns
  3058. if (!g_isalive[id] || g_zombie[id] || g_survivor[id])
  3059. return;
  3060.  
  3061. // Bots pick their weapons randomly / Random weapons setting enabled
  3062. if (get_pcvar_num(cvar_randweapons) || g_isbot[id])
  3063. {
  3064. buy_primary_weapon(id, random_num(0, ArraySize(g_primary_items) - 1))
  3065. menu_buy2(id, random_num(0, ArraySize(g_secondary_items) - 1))
  3066. return;
  3067. }
  3068.  
  3069. // Automatic selection enabled for player and menu called on spawn event
  3070. if (WPN_AUTO_ON && taskid > g_maxplayers)
  3071. {
  3072. buy_primary_weapon(id, WPN_AUTO_PRI)
  3073. menu_buy2(id, WPN_AUTO_SEC)
  3074. return;
  3075. }
  3076.  
  3077. static menu[300], len, weap, maxloops
  3078. len = 0
  3079. maxloops = min(WPN_STARTID+7, WPN_MAXIDS)
  3080.  
  3081. // Title
  3082. len += formatex(menu[len], charsmax(menu) - len, "\y%L \r[%d-%d]^n^n", id, "MENU_BUY1_TITLE", WPN_STARTID+1, min(WPN_STARTID+7, WPN_MAXIDS))
  3083.  
  3084. // 1-7. Weapon List
  3085. for (weap = WPN_STARTID; weap < maxloops; weap++)
  3086. len += formatex(menu[len], charsmax(menu) - len, "\r%d.\w %s^n", weap-WPN_STARTID+1, WEAPONNAMES[ArrayGetCell(g_primary_weaponids, weap)])
  3087.  
  3088. // 8. Auto Select
  3089. len += formatex(menu[len], charsmax(menu) - len, "^n\r8.\w %L \y[%L]", id, "MENU_AUTOSELECT", id, (WPN_AUTO_ON) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3090.  
  3091. // 9. Next/Back - 0. Exit
  3092. len += formatex(menu[len], charsmax(menu) - len, "^n^n\r9.\w %L/%L^n^n\r0.\w %L", id, "MENU_NEXT", id, "MENU_BACK", id, "MENU_EXIT")
  3093.  
  3094. show_menu(id, KEYSMENU, menu, -1, "Buy Menu 1")
  3095. }
  3096.  
  3097. // Buy Menu 2
  3098. show_menu_buy2(id)
  3099. {
  3100. static menu[250], len, weap, maxloops
  3101. len = 0
  3102. maxloops = ArraySize(g_secondary_items)
  3103.  
  3104. // Title
  3105. len += formatex(menu[len], charsmax(menu) - len, "\y%L^n", id, "MENU_BUY2_TITLE")
  3106.  
  3107. // 1-6. Weapon List
  3108. for (weap = 0; weap < maxloops; weap++)
  3109. len += formatex(menu[len], charsmax(menu) - len, "^n\r%d.\w %s", weap+1, WEAPONNAMES[ArrayGetCell(g_secondary_weaponids, weap)])
  3110.  
  3111. // 8. Auto Select
  3112. len += formatex(menu[len], charsmax(menu) - len, "^n^n\r8.\w %L \y[%L]", id, "MENU_AUTOSELECT", id, (WPN_AUTO_ON) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3113.  
  3114. // 0. Exit
  3115. len += formatex(menu[len], charsmax(menu) - len, "^n^n\r0.\w %L", id, "MENU_EXIT")
  3116.  
  3117. show_menu(id, KEYSMENU, menu, -1, "Buy Menu 2")
  3118. }
  3119.  
  3120. // Extra Items Menu
  3121. show_menu_extras(id)
  3122. {
  3123. static menuid, menu[128], item, team, buffer[32]
  3124.  
  3125. // Title
  3126. formatex(menu, charsmax(menu), "%L [%L]\r", id, "MENU_EXTRA_TITLE", id, g_zombie[id] ? g_nemesis[id] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE" : g_survivor[id] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
  3127. menuid = menu_create(menu, "menu_extras")
  3128.  
  3129. // Item List
  3130. for (item = 0; item < g_extraitem_i; item++)
  3131. {
  3132. // Retrieve item's team
  3133. team = ArrayGetCell(g_extraitem_team, item)
  3134.  
  3135. // Item not available to player's team/class
  3136. if ((g_zombie[id] && !g_nemesis[id] && !(team & ZP_TEAM_ZOMBIE)) || (!g_zombie[id] && !g_survivor[id] && !(team & ZP_TEAM_HUMAN)) || (g_nemesis[id] && !(team & ZP_TEAM_NEMESIS)) || (g_survivor[id] && !(team & ZP_TEAM_SURVIVOR)))
  3137. continue;
  3138.  
  3139. // Check if it's one of the hardcoded items, check availability, set translated caption
  3140. switch (item)
  3141. {
  3142. case EXTRA_NVISION:
  3143. {
  3144. if (!get_pcvar_num(cvar_extranvision)) continue;
  3145. formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA1")
  3146. }
  3147. case EXTRA_ANTIDOTE:
  3148. {
  3149. if (!get_pcvar_num(cvar_extraantidote) || g_antidotecounter >= get_pcvar_num(cvar_antidotelimit)) continue;
  3150. formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA2")
  3151. }
  3152. case EXTRA_MADNESS:
  3153. {
  3154. if (!get_pcvar_num(cvar_extramadness) || g_madnesscounter >= get_pcvar_num(cvar_madnesslimit)) continue;
  3155. formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA3")
  3156. }
  3157. case EXTRA_INFBOMB:
  3158. {
  3159. if (!get_pcvar_num(cvar_extrainfbomb) || g_infbombcounter >= get_pcvar_num(cvar_infbomblimit)) continue;
  3160. formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA4")
  3161. }
  3162. default:
  3163. {
  3164. if (item >= EXTRA_WEAPONS_STARTID && item <= EXTRAS_CUSTOM_STARTID-1 && !get_pcvar_num(cvar_extraweapons)) continue;
  3165. ArrayGetString(g_extraitem_name, item, buffer, charsmax(buffer))
  3166. }
  3167. }
  3168.  
  3169. // Add Item Name and Cost
  3170. formatex(menu, charsmax(menu), "%s \y%d %L", buffer, ArrayGetCell(g_extraitem_cost, item), id, "AMMO_PACKS2")
  3171. buffer[0] = item
  3172. buffer[1] = 0
  3173. menu_additem(menuid, menu, buffer)
  3174. }
  3175.  
  3176. // No items to display?
  3177. if (menu_items(menuid) <= 0)
  3178. {
  3179. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id ,"CMD_NOT_EXTRAS")
  3180. menu_destroy(menuid)
  3181. return;
  3182. }
  3183.  
  3184. // Back - Next - Exit
  3185. formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
  3186. menu_setprop(menuid, MPROP_BACKNAME, menu)
  3187. formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
  3188. menu_setprop(menuid, MPROP_NEXTNAME, menu)
  3189. formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
  3190. menu_setprop(menuid, MPROP_EXITNAME, menu)
  3191.  
  3192. menu_display(id, menuid)
  3193. }
  3194.  
  3195. // Zombie Class Menu
  3196. public show_menu_zclass(id)
  3197. {
  3198. // Player disconnected
  3199. if (!g_isconnected[id])
  3200. return;
  3201.  
  3202. // Bots pick their zombie class randomly
  3203. if (g_isbot[id])
  3204. {
  3205. g_zombieclassnext[id] = random_num(0, g_zclass_i - 1)
  3206. return;
  3207. }
  3208.  
  3209. static menuid, menu[128], class, buffer[32], buffer2[32]
  3210.  
  3211. // Title
  3212. formatex(menu, charsmax(menu), "%L\r", id, "MENU_ZCLASS_TITLE")
  3213. menuid = menu_create(menu, "menu_zclass")
  3214.  
  3215. // Class List
  3216. for (class = 0; class < g_zclass_i; class++)
  3217. {
  3218. // Retrieve name and info
  3219. ArrayGetString(g_zclass_name, class, buffer, charsmax(buffer))
  3220. ArrayGetString(g_zclass_info, class, buffer2, charsmax(buffer2))
  3221.  
  3222. // Add to menu
  3223. if (class == g_zombieclassnext[id])
  3224. formatex(menu, charsmax(menu), "\d%s %s", buffer, buffer2)
  3225. else
  3226. formatex(menu, charsmax(menu), "%s \y%s", buffer, buffer2)
  3227.  
  3228. buffer[0] = class
  3229. buffer[1] = 0
  3230. menu_additem(menuid, menu, buffer)
  3231. }
  3232.  
  3233. // Back - Next - Exit
  3234. formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
  3235. menu_setprop(menuid, MPROP_BACKNAME, menu)
  3236. formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
  3237. menu_setprop(menuid, MPROP_NEXTNAME, menu)
  3238. formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
  3239. menu_setprop(menuid, MPROP_EXITNAME, menu)
  3240.  
  3241. menu_display(id, menuid)
  3242. }
  3243.  
  3244. // Help Menu
  3245. show_menu_info(id)
  3246. {
  3247. static menu[150]
  3248.  
  3249. formatex(menu, charsmax(menu), "\y%L^n^n\r1.\w %L^n\r2.\w %L^n\r3.\w %L^n\r4.\w %L^n^n\r0.\w %L", id, "MENU_INFO_TITLE", id, "MENU_INFO1", id,"MENU_INFO2", id,"MENU_INFO3", id,"MENU_INFO4", id, "MENU_EXIT")
  3250. show_menu(id, KEYSMENU, menu, -1, "Mod Info")
  3251. }
  3252.  
  3253. // Admin Menu
  3254. show_menu_admin(id)
  3255. {
  3256. static menu[250], len, userflags
  3257. len = 0
  3258. userflags = get_user_flags(id)
  3259.  
  3260. // Title
  3261. len += formatex(menu[len], charsmax(menu) - len, "\y%L^n^n", id, "MENU_ADMIN_TITLE")
  3262.  
  3263. // 1. Zombiefy/Humanize command
  3264. if (userflags & (g_access_flag[ACCESS_MODE_INFECTION] | g_access_flag[ACCESS_MAKE_ZOMBIE] | g_access_flag[ACCESS_MAKE_HUMAN]))
  3265. len += formatex(menu[len], charsmax(menu) - len, "\r1.\w %L^n", id, "MENU_ADMIN1")
  3266. else
  3267. len += formatex(menu[len], charsmax(menu) - len, "\d1. %L^n", id, "MENU_ADMIN1")
  3268.  
  3269. // 2. Nemesis command
  3270. if (userflags & (g_access_flag[ACCESS_MODE_NEMESIS] | g_access_flag[ACCESS_MAKE_NEMESIS]))
  3271. len += formatex(menu[len], charsmax(menu) - len, "\r2.\w %L^n", id, "MENU_ADMIN2")
  3272. else
  3273. len += formatex(menu[len], charsmax(menu) - len, "\d2. %L^n", id, "MENU_ADMIN2")
  3274.  
  3275. // 3. Survivor command
  3276. if (userflags & (g_access_flag[ACCESS_MODE_SURVIVOR] | g_access_flag[ACCESS_MAKE_SURVIVOR]))
  3277. len += formatex(menu[len], charsmax(menu) - len, "\r3.\w %L^n", id, "MENU_ADMIN3")
  3278. else
  3279. len += formatex(menu[len], charsmax(menu) - len, "\d3. %L^n", id, "MENU_ADMIN3")
  3280.  
  3281. // 4. Respawn command
  3282. if (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS])
  3283. len += formatex(menu[len], charsmax(menu) - len, "\r4.\w %L^n", id, "MENU_ADMIN4")
  3284. else
  3285. len += formatex(menu[len], charsmax(menu) - len, "\d4. %L^n", id, "MENU_ADMIN4")
  3286.  
  3287. // 5. Swarm mode command
  3288. if ((userflags & g_access_flag[ACCESS_MODE_SWARM]) && allowed_swarm())
  3289. len += formatex(menu[len], charsmax(menu) - len, "\r5.\w %L^n", id, "MENU_ADMIN5")
  3290. else
  3291. len += formatex(menu[len], charsmax(menu) - len, "\d5. %L^n", id, "MENU_ADMIN5")
  3292.  
  3293. // 6. Multi infection command
  3294. if ((userflags & g_access_flag[ACCESS_MODE_MULTI]) && allowed_multi())
  3295. len += formatex(menu[len], charsmax(menu) - len, "\r6.\w %L^n", id, "MENU_ADMIN6")
  3296. else
  3297. len += formatex(menu[len], charsmax(menu) - len, "\d6. %L^n", id, "MENU_ADMIN6")
  3298.  
  3299. // 7. Plague mode command
  3300. if ((userflags & g_access_flag[ACCESS_MODE_PLAGUE]) && allowed_plague())
  3301. len += formatex(menu[len], charsmax(menu) - len, "\r7.\w %L^n", id, "MENU_ADMIN7")
  3302. else
  3303. len += formatex(menu[len], charsmax(menu) - len, "\d7. %L^n", id, "MENU_ADMIN7")
  3304.  
  3305. // 0. Exit
  3306. len += formatex(menu[len], charsmax(menu) - len, "^n\r0.\w %L", id, "MENU_EXIT")
  3307.  
  3308. show_menu(id, KEYSMENU, menu, -1, "Admin Menu")
  3309. }
  3310.  
  3311. // Player List Menu
  3312. show_menu_player_list(id)
  3313. {
  3314. static menuid, menu[128], player, userflags, buffer[2]
  3315. userflags = get_user_flags(id)
  3316.  
  3317. // Title
  3318. switch (PL_ACTION)
  3319. {
  3320. case ACTION_ZOMBIEFY_HUMANIZE: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN1")
  3321. case ACTION_MAKE_NEMESIS: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN2")
  3322. case ACTION_MAKE_SURVIVOR: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN3")
  3323. case ACTION_RESPAWN_PLAYER: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN4")
  3324. }
  3325. menuid = menu_create(menu, "menu_player_list")
  3326.  
  3327. // Player List
  3328. for (player = 0; player <= g_maxplayers; player++)
  3329. {
  3330. // Skip if not connected
  3331. if (!g_isconnected[player])
  3332. continue;
  3333.  
  3334. // Format text depending on the action to take
  3335. switch (PL_ACTION)
  3336. {
  3337. case ACTION_ZOMBIEFY_HUMANIZE: // Zombiefy/Humanize command
  3338. {
  3339. if (g_zombie[player])
  3340. {
  3341. if (allowed_human(player) && (userflags & g_access_flag[ACCESS_MAKE_HUMAN]))
  3342. formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
  3343. else
  3344. formatex(menu, charsmax(menu), "\d%s [%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
  3345. }
  3346. else
  3347. {
  3348. if (allowed_zombie(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_INFECTION]) : (userflags & g_access_flag[ACCESS_MAKE_ZOMBIE])))
  3349. formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
  3350. else
  3351. formatex(menu, charsmax(menu), "\d%s [%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
  3352. }
  3353. }
  3354. case ACTION_MAKE_NEMESIS: // Nemesis command
  3355. {
  3356. if (allowed_nemesis(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_NEMESIS]) : (userflags & g_access_flag[ACCESS_MAKE_NEMESIS])))
  3357. {
  3358. if (g_zombie[player])
  3359. formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
  3360. else
  3361. formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
  3362. }
  3363. else
  3364. formatex(menu, charsmax(menu), "\d%s [%L]", g_playername[player], id, g_zombie[player] ? g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE" : g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
  3365. }
  3366. case ACTION_MAKE_SURVIVOR: // Survivor command
  3367. {
  3368. if (allowed_survivor(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_SURVIVOR]) : (userflags & g_access_flag[ACCESS_MAKE_SURVIVOR])))
  3369. {
  3370. if (g_zombie[player])
  3371. formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
  3372. else
  3373. formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
  3374. }
  3375. else
  3376. formatex(menu, charsmax(menu), "\d%s [%L]", g_playername[player], id, g_zombie[player] ? g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE" : g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
  3377. }
  3378. case ACTION_RESPAWN_PLAYER: // Respawn command
  3379. {
  3380. if (allowed_respawn(player) && (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS]))
  3381. formatex(menu, charsmax(menu), "%s", g_playername[player])
  3382. else
  3383. formatex(menu, charsmax(menu), "\d%s", g_playername[player])
  3384. }
  3385. }
  3386.  
  3387. // Add player
  3388. buffer[0] = player
  3389. buffer[1] = 0
  3390. menu_additem(menuid, menu, buffer)
  3391. }
  3392.  
  3393. // Back - Next - Exit
  3394. formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
  3395. menu_setprop(menuid, MPROP_BACKNAME, menu)
  3396. formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
  3397. menu_setprop(menuid, MPROP_NEXTNAME, menu)
  3398. formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
  3399. menu_setprop(menuid, MPROP_EXITNAME, menu)
  3400.  
  3401. menu_display(id, menuid)
  3402. }
  3403.  
  3404. /*================================================================================
  3405. [Menu Handlers]
  3406. =================================================================================*/
  3407.  
  3408. // Game Menu
  3409. public menu_game(id, key)
  3410. {
  3411. switch (key)
  3412. {
  3413. case 0: // Buy Weapons
  3414. {
  3415. // Custom buy menus enabled?
  3416. if (get_pcvar_num(cvar_buycustom))
  3417. {
  3418. // Disable the remember selection setting
  3419. WPN_AUTO_ON = 0
  3420. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "BUY_ENABLED")
  3421.  
  3422. // Show menu if player hasn't yet bought anything
  3423. if (g_canbuy[id]) show_menu_buy1(id)
  3424. }
  3425. else
  3426. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT")
  3427. }
  3428. case 1: // Extra Items
  3429. {
  3430. // Extra items enabled?
  3431. if (get_pcvar_num(cvar_extraitems))
  3432. {
  3433. // Check whether the player is able to buy anything
  3434. if (g_isalive[id])
  3435. show_menu_extras(id)
  3436. else
  3437. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT")
  3438. }
  3439. else
  3440. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_EXTRAS")
  3441. }
  3442. case 2: // Zombie Classes
  3443. {
  3444. // Zombie classes enabled?
  3445. if (get_pcvar_num(cvar_zclasses))
  3446. show_menu_zclass(id)
  3447. else
  3448. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_ZCLASSES")
  3449. }
  3450. case 3: // Unstuck
  3451. {
  3452. // Check if player is stuck
  3453. if (g_isalive[id])
  3454. {
  3455. if (is_player_stuck(id))
  3456. {
  3457. // Move to an initial spawn
  3458. if (get_pcvar_num(cvar_randspawn))
  3459. do_random_spawn(id) // random spawn (including CSDM)
  3460. else
  3461. do_random_spawn(id, 1) // regular spawn
  3462. }
  3463. else
  3464. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_STUCK")
  3465. }
  3466. else
  3467. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT")
  3468. }
  3469. case 4: // Help Menu
  3470. {
  3471. show_menu_info(id)
  3472. }
  3473. case 5: // Join Spectator
  3474. {
  3475. // Player alive?
  3476. if (g_isalive[id])
  3477. {
  3478. // Prevent abuse by non-admins if block suicide setting is enabled
  3479. if (get_pcvar_num(cvar_blocksuicide) && !(get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MENU]))
  3480. {
  3481. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT")
  3482. return PLUGIN_HANDLED;
  3483. }
  3484.  
  3485. // Check that we still have both humans and zombies to keep the round going
  3486. check_round(id)
  3487.  
  3488. // Kill him before he switches team
  3489. dllfunc(DLLFunc_ClientKill, id)
  3490. }
  3491.  
  3492. // Temporarily save player stats?
  3493. if (get_pcvar_num(cvar_statssave)) save_stats(id)
  3494.  
  3495. // Remove previous tasks
  3496. remove_task(id+TASK_TEAM)
  3497. remove_task(id+TASK_MODEL)
  3498. remove_task(id+TASK_FLASH)
  3499. remove_task(id+TASK_CHARGE)
  3500. remove_task(id+TASK_SPAWN)
  3501. remove_task(id+TASK_BLOOD)
  3502. remove_task(id+TASK_AURA)
  3503. remove_task(id+TASK_BURN)
  3504.  
  3505. // Then move him to the spectator team
  3506. fm_cs_set_user_team(id, FM_CS_TEAM_SPECTATOR)
  3507. fm_user_team_update(id)
  3508. }
  3509. case 8: // Admin Menu
  3510. {
  3511. // Check if player has the required access
  3512. if (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MENU])
  3513. show_menu_admin(id)
  3514. else
  3515. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_ACCESS")
  3516. }
  3517. }
  3518.  
  3519. return PLUGIN_HANDLED;
  3520. }
  3521.  
  3522. // Buy Menu 1
  3523. public menu_buy1(id, key)
  3524. {
  3525. // Zombies or survivors get no guns
  3526. if (!g_isalive[id] || g_zombie[id] || g_survivor[id])
  3527. return PLUGIN_HANDLED;
  3528.  
  3529. // Special keys / weapon list exceeded
  3530. if (key >= MENU_KEY_AUTOSELECT || WPN_SELECTION >= WPN_MAXIDS)
  3531. {
  3532. switch (key)
  3533. {
  3534. case MENU_KEY_AUTOSELECT: // toggle auto select
  3535. {
  3536. WPN_AUTO_ON = 1 - WPN_AUTO_ON
  3537. }
  3538. case MENU_KEY_NEXT: // next/back
  3539. {
  3540. if (WPN_STARTID+7 < WPN_MAXIDS)
  3541. WPN_STARTID += 7
  3542. else
  3543. WPN_STARTID = 0
  3544. }
  3545. case MENU_KEY_EXIT: // exit
  3546. {
  3547. return PLUGIN_HANDLED;
  3548. }
  3549. }
  3550.  
  3551. // Show buy menu again
  3552. show_menu_buy1(id)
  3553. return PLUGIN_HANDLED;
  3554. }
  3555.  
  3556. // Store selected weapon id
  3557. WPN_AUTO_PRI = WPN_SELECTION
  3558.  
  3559. // Buy primary weapon
  3560. buy_primary_weapon(id, WPN_AUTO_PRI)
  3561.  
  3562. // Show pistols menu
  3563. show_menu_buy2(id)
  3564.  
  3565. return PLUGIN_HANDLED;
  3566. }
  3567.  
  3568. // Buy Primary Weapon
  3569. buy_primary_weapon(id, selection)
  3570. {
  3571. // Drop previous weapons
  3572. drop_weapons(id, 1)
  3573. drop_weapons(id, 2)
  3574.  
  3575. // Strip off from weapons
  3576. fm_strip_user_weapons(id)
  3577. fm_give_item(id, "weapon_knife")
  3578.  
  3579. // Get weapon's id and name
  3580. static weaponid, wname[32]
  3581. weaponid = ArrayGetCell(g_primary_weaponids, selection)
  3582. ArrayGetString(g_primary_items, selection, wname, charsmax(wname))
  3583.  
  3584. // Give the new weapon and full ammo
  3585. fm_give_item(id, wname)
  3586. ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
  3587.  
  3588. // Weapons bought
  3589. g_canbuy[id] = false
  3590.  
  3591. // Give additional items
  3592. static i
  3593. for (i = 0; i < ArraySize(g_additional_items); i++)
  3594. {
  3595. ArrayGetString(g_additional_items, i, wname, charsmax(wname))
  3596. fm_give_item(id, wname)
  3597. }
  3598. }
  3599.  
  3600. // Buy Menu 2
  3601. public menu_buy2(id, key)
  3602. {
  3603. // Zombies or survivors get no guns
  3604. if (!g_isalive[id] || g_zombie[id] || g_survivor[id])
  3605. return PLUGIN_HANDLED;
  3606.  
  3607. // Special keys / weapon list exceeded
  3608. if (key >= ArraySize(g_secondary_items))
  3609. {
  3610. // Toggle autoselect
  3611. if (key == MENU_KEY_AUTOSELECT)
  3612. WPN_AUTO_ON = 1 - WPN_AUTO_ON
  3613.  
  3614. // Reshow menu unless user exited
  3615. if (key != MENU_KEY_EXIT)
  3616. show_menu_buy2(id)
  3617.  
  3618. return PLUGIN_HANDLED;
  3619. }
  3620.  
  3621. // Store selected weapon
  3622. WPN_AUTO_SEC = key
  3623.  
  3624. // Drop secondary gun again, in case we picked another (bugfix)
  3625. drop_weapons(id, 2)
  3626.  
  3627. // Get weapon's id
  3628. static weaponid, wname[32]
  3629. weaponid = ArrayGetCell(g_secondary_weaponids, key)
  3630. ArrayGetString(g_secondary_items, key, wname, charsmax(wname))
  3631.  
  3632. // Give the new weapon and full ammo
  3633. fm_give_item(id, wname)
  3634. ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
  3635.  
  3636. return PLUGIN_HANDLED;
  3637. }
  3638.  
  3639. // Extra Items Menu
  3640. public menu_extras(id, menuid, item)
  3641. {
  3642. // Menu was closed
  3643. if (item == MENU_EXIT)
  3644. {
  3645. menu_destroy(menuid)
  3646. return PLUGIN_HANDLED;
  3647. }
  3648.  
  3649. // Dead players are not allowed to buy items
  3650. if (!g_isalive[id])
  3651. {
  3652. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT")
  3653. menu_destroy(menuid)
  3654. return PLUGIN_HANDLED;
  3655. }
  3656.  
  3657. // Retrieve extra item id
  3658. static buffer[2], dummy, itemid
  3659. menu_item_getinfo(menuid, item, dummy, buffer, charsmax(buffer), _, _, dummy)
  3660. itemid = buffer[0]
  3661.  
  3662. // Attempt to buy the item
  3663. buy_extra_item(id, itemid)
  3664. menu_destroy(menuid)
  3665. return PLUGIN_HANDLED;
  3666. }
  3667.  
  3668. // Buy Extra Item
  3669. buy_extra_item(id, itemid, ignorecost = 0)
  3670. {
  3671. // Retrieve item's team
  3672. static team
  3673. team = ArrayGetCell(g_extraitem_team, itemid)
  3674.  
  3675. // Check for team/class specific items
  3676. if ((g_zombie[id] && !g_nemesis[id] && !(team & ZP_TEAM_ZOMBIE)) || (!g_zombie[id] && !g_survivor[id] && !(team & ZP_TEAM_HUMAN)) || (g_nemesis[id] && !(team & ZP_TEAM_NEMESIS)) || (g_survivor[id] && !(team & ZP_TEAM_SURVIVOR)))
  3677. {
  3678. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT")
  3679. return;
  3680. }
  3681.  
  3682. // Check for unavailable items
  3683. if ((itemid == EXTRA_NVISION && !get_pcvar_num(cvar_extranvision))
  3684. || (itemid == EXTRA_ANTIDOTE && (!get_pcvar_num(cvar_extraantidote) || g_antidotecounter >= get_pcvar_num(cvar_antidotelimit)))
  3685. || (itemid == EXTRA_MADNESS && (!get_pcvar_num(cvar_extramadness) || g_madnesscounter >= get_pcvar_num(cvar_madnesslimit)))
  3686. || (itemid == EXTRA_INFBOMB && (!get_pcvar_num(cvar_extrainfbomb) || g_infbombcounter >= get_pcvar_num(cvar_infbomblimit)))
  3687. || (itemid >= EXTRA_WEAPONS_STARTID && itemid <= EXTRAS_CUSTOM_STARTID-1 && !get_pcvar_num(cvar_extraweapons)))
  3688. {
  3689. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT")
  3690. return;
  3691. }
  3692.  
  3693. // Check for hard coded items with special conditions
  3694. if ((itemid == EXTRA_ANTIDOTE && (g_endround || g_swarmround || g_nemround || g_survround || g_plagueround || fnGetZombies() <= 1 || (get_pcvar_num(cvar_deathmatch) && !get_pcvar_num(cvar_respawnafterlast) && fnGetHumans() == 1)))
  3695. || (itemid == EXTRA_MADNESS && g_nodamage[id]) || (itemid == EXTRA_INFBOMB && (g_endround || g_swarmround || g_nemround || g_survround || g_plagueround)))
  3696. {
  3697. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_CANTUSE")
  3698. return;
  3699. }
  3700.  
  3701. // Ignore item's cost?
  3702. if (!ignorecost)
  3703. {
  3704. // Check that we have enough ammo packs
  3705. if (g_ammopacks[id] < ArrayGetCell(g_extraitem_cost, itemid))
  3706. {
  3707. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "NOT_ENOUGH_AMMO")
  3708. return;
  3709. }
  3710.  
  3711. // Deduce item cost
  3712. g_ammopacks[id] -= ArrayGetCell(g_extraitem_cost, itemid)
  3713. }
  3714.  
  3715. // Check which kind of item we're buying
  3716. switch (itemid)
  3717. {
  3718. case EXTRA_NVISION: // Night Vision
  3719. {
  3720. g_nvision[id] = true
  3721.  
  3722. if (!g_isbot[id])
  3723. {
  3724. g_nvisionenabled[id] = true
  3725.  
  3726. // Custom nvg?
  3727. if (get_pcvar_num(cvar_customnvg))
  3728. {
  3729. remove_task(id+TASK_NVISION)
  3730. set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
  3731. }
  3732. else
  3733. set_user_gnvision(id, 1)
  3734. }
  3735. else
  3736. cs_set_user_nvg(id, 1)
  3737. }
  3738. case EXTRA_ANTIDOTE: // Antidote
  3739. {
  3740. // Increase antidote purchase count for this round
  3741. g_antidotecounter++
  3742.  
  3743. humanme(id, 0, 0)
  3744. }
  3745. case EXTRA_MADNESS: // Zombie Madness
  3746. {
  3747. // Increase madness purchase count for this round
  3748. g_madnesscounter++
  3749.  
  3750. g_nodamage[id] = true
  3751. set_task(0.1, "zombie_aura", id+TASK_AURA, _, _, "b")
  3752. set_task(get_pcvar_float(cvar_madnessduration), "madness_over", id+TASK_BLOOD)
  3753.  
  3754. static sound[64]
  3755. ArrayGetString(zombie_madness, random_num(0, ArraySize(zombie_madness) - 1), sound, charsmax(sound))
  3756. emit_sound(id, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  3757. }
  3758. case EXTRA_INFBOMB: // Infection Bomb
  3759. {
  3760. // Increase infection bomb purchase count for this round
  3761. g_infbombcounter++
  3762.  
  3763. // Already own one
  3764. if (user_has_weapon(id, CSW_HEGRENADE))
  3765. {
  3766. // Increase BP ammo on it instead
  3767. cs_set_user_bpammo(id, CSW_HEGRENADE, cs_get_user_bpammo(id, CSW_HEGRENADE) + 1)
  3768.  
  3769. // Flash ammo in hud
  3770. message_begin(MSG_ONE_UNRELIABLE, g_msgAmmoPickup, _, id)
  3771. write_byte(AMMOID[CSW_HEGRENADE]) // ammo id
  3772. write_byte(1) // ammo amount
  3773. message_end()
  3774.  
  3775. // Play clip purchase sound
  3776. emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
  3777.  
  3778. return; // stop here
  3779. }
  3780.  
  3781. // Give weapon to the player
  3782. fm_give_item(id, "weapon_hegrenade")
  3783. }
  3784. default:
  3785. {
  3786. if (itemid >= EXTRA_WEAPONS_STARTID && itemid <= EXTRAS_CUSTOM_STARTID-1) // Weapons
  3787. {
  3788. // Get weapon's id and name
  3789. static weaponid, wname[32]
  3790. ArrayGetString(g_extraweapon_items, itemid - EXTRA_WEAPONS_STARTID, wname, charsmax(wname))
  3791. weaponid = cs_weapon_name_to_id(wname)
  3792.  
  3793. // If we are giving a primary/secondary weapon
  3794. if (MAXBPAMMO[weaponid] > 2)
  3795. {
  3796. // Make user drop the previous one
  3797. if ((1<<weaponid) & PRIMARY_WEAPONS_BIT_SUM)
  3798. drop_weapons(id, 1)
  3799. else
  3800. drop_weapons(id, 2)
  3801.  
  3802. // Give full BP ammo for the new one
  3803. ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
  3804. }
  3805. // If we are giving a grenade which the user already owns
  3806. else if (user_has_weapon(id, weaponid))
  3807. {
  3808. // Increase BP ammo on it instead
  3809. cs_set_user_bpammo(id, weaponid, cs_get_user_bpammo(id, weaponid) + 1)
  3810.  
  3811. // Flash ammo in hud
  3812. message_begin(MSG_ONE_UNRELIABLE, g_msgAmmoPickup, _, id)
  3813. write_byte(AMMOID[weaponid]) // ammo id
  3814. write_byte(1) // ammo amount
  3815. message_end()
  3816.  
  3817. // Play clip purchase sound
  3818. emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
  3819.  
  3820. return; // stop here
  3821. }
  3822.  
  3823. // Give weapon to the player
  3824. fm_give_item(id, wname)
  3825. }
  3826. else // Custom additions
  3827. {
  3828. // Item selected forward
  3829. ExecuteForward(g_fwExtraItemSelected, g_fwDummyResult, id, itemid);
  3830.  
  3831. // Item purchase blocked, restore buyer's ammo packs
  3832. if (g_fwDummyResult >= ZP_PLUGIN_HANDLED && !ignorecost)
  3833. g_ammopacks[id] += ArrayGetCell(g_extraitem_cost, itemid)
  3834. }
  3835. }
  3836. }
  3837. }
  3838.  
  3839. // Zombie Class Menu
  3840. public menu_zclass(id, menuid, item)
  3841. {
  3842. // Menu was closed
  3843. if (item == MENU_EXIT)
  3844. {
  3845. menu_destroy(menuid)
  3846. return PLUGIN_HANDLED;
  3847. }
  3848.  
  3849. // Retrieve zombie class id
  3850. static buffer[2], dummy, classid
  3851. menu_item_getinfo(menuid, item, dummy, buffer, charsmax(buffer), _, _, dummy)
  3852. classid = buffer[0]
  3853.  
  3854. // Store selection for the next infection
  3855. g_zombieclassnext[id] = classid
  3856.  
  3857. static name[32]
  3858. ArrayGetString(g_zclass_name, g_zombieclassnext[id], name, charsmax(name))
  3859.  
  3860. // Show selected zombie class info and stats
  3861. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L: %s", id, "ZOMBIE_SELECT", name)
  3862. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L: %d %L: %d %L: %d %L: %d%%", id, "ZOMBIE_ATTRIB1", ArrayGetCell(g_zclass_hp, g_zombieclassnext[id]), id, "ZOMBIE_ATTRIB2", ArrayGetCell(g_zclass_spd, g_zombieclassnext[id]),
  3863. id, "ZOMBIE_ATTRIB3", floatround(Float:ArrayGetCell(g_zclass_grav, g_zombieclassnext[id]) * 800.0), id, "ZOMBIE_ATTRIB4", floatround(Float:ArrayGetCell(g_zclass_kb, g_zombieclassnext[id]) * 100.0))
  3864.  
  3865. menu_destroy(menuid)
  3866. return PLUGIN_HANDLED;
  3867. }
  3868.  
  3869. // Info Menu
  3870. public menu_info(id, key)
  3871. {
  3872. static motd[1500], len
  3873. len = 0
  3874.  
  3875. switch (key)
  3876. {
  3877. case 0: // General
  3878. {
  3879. static weather, lighting[2]
  3880. weather = 0
  3881. get_pcvar_string(cvar_lighting, lighting, charsmax(lighting))
  3882. strtolower(lighting)
  3883.  
  3884. len += formatex(motd[len], charsmax(motd) - len, "%L ", id, "MOTD_INFO11", "Zombie Plague", PLUGIN_VERSION, "MeRcyLeZZ")
  3885. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO12")
  3886. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_A")
  3887.  
  3888. if (g_ambience_fog)
  3889. {
  3890. len += formatex(motd[len], charsmax(motd) - len, (weather < 1) ? " %L" : ". %L", id, "MOTD_FOG")
  3891. weather++
  3892. }
  3893. if (g_ambience_rain)
  3894. {
  3895. len += formatex(motd[len], charsmax(motd) - len, (weather < 1) ? " %L" : ". %L", id, "MOTD_RAIN")
  3896. weather++
  3897. }
  3898. if (g_ambience_snow)
  3899. {
  3900. len += formatex(motd[len], charsmax(motd) - len, (weather < 1) ? " %L" : ". %L", id, "MOTD_SNOW")
  3901. weather++
  3902. }
  3903. if (weather < 1) len += formatex(motd[len], charsmax(motd) - len, " %L", id, "MOTD_DISABLED")
  3904.  
  3905. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_B", lighting)
  3906. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_C", id, get_pcvar_num(cvar_triggered) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3907. if (lighting[0] >= 'a' && lighting[0] <= 'd' && get_pcvar_float(cvar_thunder) > 0.0) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_D", floatround(get_pcvar_float(cvar_thunder)))
  3908. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_E", id, get_pcvar_num(cvar_removedoors) > 0 ? get_pcvar_num(cvar_removedoors) > 1 ? "MOTD_DOORS" : "MOTD_ROTATING" : "MOTD_ENABLED")
  3909. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_F", id, get_pcvar_num(cvar_deathmatch) > 0 ? get_pcvar_num(cvar_deathmatch) > 1 ? get_pcvar_num(cvar_deathmatch) > 2 ? "MOTD_ENABLED" : "MOTD_DM_ZOMBIE" : "MOTD_DM_HUMAN" : "MOTD_DISABLED")
  3910. if (get_pcvar_num(cvar_deathmatch)) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_G", floatround(get_pcvar_float(cvar_spawnprotection)))
  3911. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_H", id, get_pcvar_num(cvar_randspawn) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3912. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_I", id, get_pcvar_num(cvar_extraitems) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3913. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_J", id, get_pcvar_num(cvar_zclasses) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3914. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_K", id, get_pcvar_num(cvar_customnvg) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3915. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_L", id, g_cached_customflash ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3916.  
  3917. show_motd(id, motd)
  3918. }
  3919. case 1: // Humans
  3920. {
  3921. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2")
  3922. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_A", get_pcvar_num(cvar_humanhp))
  3923. if (get_pcvar_num(cvar_humanlasthp) > 0) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_B", get_pcvar_num(cvar_humanlasthp))
  3924. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_C", floatround(g_cached_humanspd))
  3925. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_D", floatround(get_pcvar_float(cvar_humangravity) * 800.0))
  3926. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_E", id, get_pcvar_num(cvar_infammo) > 0 ? get_pcvar_num(cvar_infammo) > 1 ? "MOTD_AMMO_CLIP" : "MOTD_AMMO_BP" : "MOTD_LIMITED")
  3927. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_F", get_pcvar_num(cvar_ammodamage))
  3928. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_G", id, get_pcvar_num(cvar_firegrenades) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3929. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_H", id, get_pcvar_num(cvar_frostgrenades) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3930. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_I", id, get_pcvar_num(cvar_flaregrenades) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3931. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_J", id, get_pcvar_num(cvar_knockback) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3932.  
  3933. show_motd(id, motd)
  3934. }
  3935. case 2: // Zombies
  3936. {
  3937. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3")
  3938. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_A", ArrayGetCell(g_zclass_hp, 0))
  3939. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_B", floatround(float(ArrayGetCell(g_zclass_hp, 0)) * get_pcvar_float(cvar_zombiefirsthp)))
  3940. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_C", floatround(get_pcvar_float(cvar_zombiearmor) * 100.0))
  3941. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_D", ArrayGetCell(g_zclass_spd, 0))
  3942. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_E", floatround(Float:ArrayGetCell(g_zclass_grav, 0) * 800.0))
  3943. if (get_pcvar_num(cvar_zombiebonushp)) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_F", get_pcvar_num(cvar_zombiebonushp))
  3944. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_G", id, get_pcvar_num(cvar_zombiepainfree) > 0 ? get_pcvar_num(cvar_zombiepainfree) > 1 ? "MOTD_LASTZOMBIE" : "MOTD_ENABLED" : "MOTD_DISABLED")
  3945. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_H", id, get_pcvar_num(cvar_zombiebleeding) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3946. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_I", get_pcvar_num(cvar_ammoinfect))
  3947.  
  3948. show_motd(id, motd)
  3949. }
  3950. case 3: // Gameplay Modes
  3951. {
  3952. static nemhp[5], survhp[5]
  3953.  
  3954. // Get nemesis and survivor health
  3955. num_to_str(get_pcvar_num(cvar_nemhp), nemhp, charsmax(nemhp))
  3956. num_to_str(get_pcvar_num(cvar_survhp), survhp, charsmax(survhp))
  3957.  
  3958. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4")
  3959. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_A", id, get_pcvar_num(cvar_nem) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3960. if (get_pcvar_num(cvar_nem))
  3961. {
  3962. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_B", get_pcvar_num(cvar_nemchance))
  3963. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_C", get_pcvar_num(cvar_nemhp) > 0 ? nemhp : "[Auto]")
  3964. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_D", floatround(g_cached_nemspd))
  3965. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_E", floatround(get_pcvar_float(cvar_nemgravity) * 800.0))
  3966. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_F", id, g_cached_leapnemesis ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3967. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_G", id, get_pcvar_num(cvar_nempainfree) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3968. }
  3969. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_H", id, get_pcvar_num(cvar_surv) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3970. if (get_pcvar_num(cvar_surv))
  3971. {
  3972. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_I", get_pcvar_num(cvar_survchance))
  3973. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_J", get_pcvar_num(cvar_survhp) > 0 ? survhp : "[Auto]")
  3974. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_K", floatround(g_cached_survspd))
  3975. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_L", floatround(get_pcvar_float(cvar_survgravity) * 800.0))
  3976. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_M", id, g_cached_leapsurvivor ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3977. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_N", id, get_pcvar_num(cvar_survpainfree) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3978. }
  3979. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_O", id, get_pcvar_num(cvar_swarm) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3980. if (get_pcvar_num(cvar_swarm)) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_P", get_pcvar_num(cvar_swarmchance))
  3981. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_Q", id, get_pcvar_num(cvar_multi) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3982. if (get_pcvar_num(cvar_multi))
  3983. {
  3984. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_R", get_pcvar_num(cvar_multichance))
  3985. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_S", floatround(get_pcvar_float(cvar_multiratio) * 100.0))
  3986. }
  3987. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_T", id, get_pcvar_num(cvar_plague) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3988. if (get_pcvar_num(cvar_plague))
  3989. {
  3990. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_U", get_pcvar_num(cvar_plaguechance))
  3991. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_V", floatround(get_pcvar_float(cvar_plagueratio) * 100.0))
  3992. }
  3993.  
  3994. show_motd(id, motd)
  3995. }
  3996. default: return PLUGIN_HANDLED;
  3997. }
  3998.  
  3999. // Show help menu again if user wishes to read another topic
  4000. show_menu_info(id)
  4001.  
  4002. return PLUGIN_HANDLED;
  4003. }
  4004.  
  4005. // Admin Menu
  4006. public menu_admin(id, key)
  4007. {
  4008. static userflags
  4009. userflags = get_user_flags(id)
  4010.  
  4011. switch (key)
  4012. {
  4013. case ACTION_ZOMBIEFY_HUMANIZE: // Zombiefy/Humanize command
  4014. {
  4015. if (userflags & (g_access_flag[ACCESS_MODE_INFECTION] | g_access_flag[ACCESS_MAKE_ZOMBIE] | g_access_flag[ACCESS_MAKE_HUMAN]))
  4016. {
  4017. // Show player list for admin to pick a target
  4018. PL_ACTION = ACTION_ZOMBIEFY_HUMANIZE
  4019. show_menu_player_list(id)
  4020. }
  4021. else
  4022. {
  4023. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_ACCESS")
  4024. show_menu_admin(id)
  4025. }
  4026. }
  4027. case ACTION_MAKE_NEMESIS: // Nemesis command
  4028. {
  4029. if (userflags & (g_access_flag[ACCESS_MODE_NEMESIS] | g_access_flag[ACCESS_MAKE_NEMESIS]))
  4030. {
  4031. // Show player list for admin to pick a target
  4032. PL_ACTION = ACTION_MAKE_NEMESIS
  4033. show_menu_player_list(id)
  4034. }
  4035. else
  4036. {
  4037. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_ACCESS")
  4038. show_menu_admin(id)
  4039. }
  4040. }
  4041. case ACTION_MAKE_SURVIVOR: // Survivor command
  4042. {
  4043. if (userflags & (g_access_flag[ACCESS_MODE_SURVIVOR] | g_access_flag[ACCESS_MAKE_SURVIVOR]))
  4044. {
  4045. // Show player list for admin to pick a target
  4046. PL_ACTION = ACTION_MAKE_SURVIVOR
  4047. show_menu_player_list(id)
  4048. }
  4049. else
  4050. {
  4051. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_ACCESS")
  4052. show_menu_admin(id)
  4053. }
  4054. }
  4055. case ACTION_RESPAWN_PLAYER: // Respawn command
  4056. {
  4057. if (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS])
  4058. {
  4059. // Show player list for admin to pick a target
  4060. PL_ACTION = ACTION_RESPAWN_PLAYER
  4061. show_menu_player_list(id)
  4062. }
  4063. else
  4064. {
  4065. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_ACCESS")
  4066. show_menu_admin(id)
  4067. }
  4068. }
  4069. case ACTION_MODE_SWARM: // Swarm Mode command
  4070. {
  4071. if (userflags & g_access_flag[ACCESS_MODE_SWARM])
  4072. {
  4073. if (allowed_swarm())
  4074. command_swarm(id)
  4075. else
  4076. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT")
  4077. }
  4078. else
  4079. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_ACCESS")
  4080.  
  4081. show_menu_admin(id)
  4082. }
  4083. case ACTION_MODE_MULTI: // Multiple Infection command
  4084. {
  4085. if (userflags & g_access_flag[ACCESS_MODE_MULTI])
  4086. {
  4087. if (allowed_multi())
  4088. command_multi(id)
  4089. else
  4090. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT")
  4091. }
  4092. else
  4093. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_ACCESS")
  4094.  
  4095. show_menu_admin(id)
  4096. }
  4097. case ACTION_MODE_PLAGUE: // Plague Mode command
  4098. {
  4099. if (userflags & g_access_flag[ACCESS_MODE_PLAGUE])
  4100. {
  4101. if (allowed_plague())
  4102. command_plague(id)
  4103. else
  4104. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT")
  4105. }
  4106. else
  4107. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_ACCESS")
  4108.  
  4109. show_menu_admin(id)
  4110. }
  4111. }
  4112.  
  4113. return PLUGIN_HANDLED;
  4114. }
  4115.  
  4116. // Player List Menu
  4117. public menu_player_list(id, menuid, item)
  4118. {
  4119. // Menu was closed
  4120. if (item == MENU_EXIT)
  4121. {
  4122. menu_destroy(menuid)
  4123. show_menu_admin(id)
  4124. return PLUGIN_HANDLED;
  4125. }
  4126.  
  4127. // Retrieve player id
  4128. static buffer[2], dummy, playerid
  4129. menu_item_getinfo(menuid, item, dummy, buffer, charsmax(buffer), _, _, dummy)
  4130. playerid = buffer[0]
  4131.  
  4132. // Perform action on player
  4133.  
  4134. // Get admin flags
  4135. static userflags
  4136. userflags = get_user_flags(id)
  4137.  
  4138. // Make sure it's still connected
  4139. if (g_isconnected[playerid])
  4140. {
  4141. // Perform the right action if allowed
  4142. switch (PL_ACTION)
  4143. {
  4144. case ACTION_ZOMBIEFY_HUMANIZE: // Zombiefy/Humanize command
  4145. {
  4146. if (g_zombie[playerid])
  4147. {
  4148. if (userflags & g_access_flag[ACCESS_MAKE_HUMAN])
  4149. {
  4150. if (allowed_human(playerid))
  4151. command_human(id, playerid)
  4152. else
  4153. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT")
  4154. }
  4155. else
  4156. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_ACCESS")
  4157. }
  4158. else
  4159. {
  4160. if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_INFECTION]) : (userflags & g_access_flag[ACCESS_MAKE_ZOMBIE]))
  4161. {
  4162. if (allowed_zombie(playerid))
  4163. command_zombie(id, playerid)
  4164. else
  4165. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT")
  4166. }
  4167. else
  4168. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_ACCESS")
  4169. }
  4170. }
  4171. case ACTION_MAKE_NEMESIS: // Nemesis command
  4172. {
  4173. if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_NEMESIS]) : (userflags & g_access_flag[ACCESS_MAKE_NEMESIS]))
  4174. {
  4175. if (allowed_nemesis(playerid))
  4176. command_nemesis(id, playerid)
  4177. else
  4178. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT")
  4179. }
  4180. else
  4181. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_ACCESS")
  4182. }
  4183. case ACTION_MAKE_SURVIVOR: // Survivor command
  4184. {
  4185. if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_SURVIVOR]) : (userflags & g_access_flag[ACCESS_MAKE_SURVIVOR]))
  4186. {
  4187. if (allowed_survivor(playerid))
  4188. command_survivor(id, playerid)
  4189. else
  4190. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT")
  4191. }
  4192. else
  4193. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_ACCESS")
  4194. }
  4195. case ACTION_RESPAWN_PLAYER: // Respawn command
  4196. {
  4197. if (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS])
  4198. {
  4199. if (allowed_respawn(playerid))
  4200. command_respawn(id, playerid)
  4201. else
  4202. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT")
  4203. }
  4204. else
  4205. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT_ACCESS")
  4206. }
  4207. }
  4208. }
  4209. else
  4210. zp_colored_print(id, "^x04[Zombie Arena]^x01 %L", id, "CMD_NOT")
  4211.  
  4212. menu_destroy(menuid)
  4213. show_menu_player_list(id)
  4214. return PLUGIN_HANDLED;
  4215. }
  4216.  
  4217. /*================================================================================
  4218. [Admin Commands]
  4219. =================================================================================*/
  4220.  
  4221. // zp_toggle [1/0]
  4222. public cmd_toggle(id, level, cid)
  4223. {
  4224. // Check for access flag - Enable/Disable Mod
  4225. if (!cmd_access(id, g_access_flag[ACCESS_ENABLE_MOD], cid, 2))
  4226. return PLUGIN_HANDLED;
  4227.  
  4228. // Retrieve arguments
  4229. new arg[2]
  4230. read_argv(1, arg, charsmax(arg))
  4231.  
  4232. // Mod already enabled/disabled
  4233. if (str_to_num(arg) == g_pluginenabled)
  4234. return PLUGIN_HANDLED;
  4235.  
  4236. // Set toggle cvar
  4237. set_pcvar_num(cvar_toggle, str_to_num(arg))
  4238. client_print(id, print_console, "Zombie Plague %L.", id, str_to_num(arg) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4239.  
  4240. // Retrieve map name
  4241. new mapname[32]
  4242. get_mapname(mapname, charsmax(mapname))
  4243.  
  4244. // Restart current map
  4245. server_cmd("changelevel %s", mapname)
  4246.  
  4247. return PLUGIN_HANDLED;
  4248. }
  4249.  
  4250. // zp_zombie [target]
  4251. public cmd_zombie(id, level, cid)
  4252. {
  4253. // Check for access flag depending on the resulting action
  4254. if (g_newround)
  4255. {
  4256. // Start Mode Infection
  4257. if (!cmd_access(id, g_access_flag[ACCESS_MODE_INFECTION], cid, 2))
  4258. return PLUGIN_HANDLED;
  4259. }
  4260. else
  4261. {
  4262. // Make Zombie
  4263. if (!cmd_access(id, g_access_flag[ACCESS_MAKE_ZOMBIE], cid, 2))
  4264. return PLUGIN_HANDLED;
  4265. }
  4266.  
  4267. // Retrieve arguments
  4268. static arg[32], player
  4269. read_argv(1, arg, charsmax(arg))
  4270. player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
  4271.  
  4272. // Invalid target
  4273. if (!player) return PLUGIN_HANDLED;
  4274.  
  4275. // Target not allowed to be zombie
  4276. if (!allowed_zombie(player))
  4277. {
  4278. client_print(id, print_console, "[Zombie Arena] %L", id, "CMD_NOT")
  4279. return PLUGIN_HANDLED
  4280. }
  4281.  
  4282. command_zombie(id, player)
  4283.  
  4284. return PLUGIN_HANDLED;
  4285. }
  4286.  
  4287. // zp_human [target]
  4288. public cmd_human(id, level, cid)
  4289. {
  4290. // Check for access flag - Make Human
  4291. if (!cmd_access(id, g_access_flag[ACCESS_MAKE_HUMAN], cid, 2))
  4292. return PLUGIN_HANDLED;
  4293.  
  4294. // Retrieve arguments
  4295. static arg[32], player
  4296. read_argv(1, arg, charsmax(arg))
  4297. player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
  4298.  
  4299. // Invalid target
  4300. if (!player) return PLUGIN_HANDLED;
  4301.  
  4302. // Target not allowed to be human
  4303. if (!allowed_human(player))
  4304. {
  4305. client_print(id, print_console, "[Zombie Arena] %L", id, "CMD_NOT")
  4306. return PLUGIN_HANDLED;
  4307. }
  4308.  
  4309. command_human(id, player)
  4310.  
  4311. return PLUGIN_HANDLED;
  4312. }
  4313.  
  4314. // zp_survivor [target]
  4315. public cmd_survivor(id, level, cid)
  4316. {
  4317. // Check for access flag depending on the resulting action
  4318. if (g_newround)
  4319. {
  4320. // Start Mode Survivor
  4321. if (!cmd_access(id, g_access_flag[ACCESS_MODE_SURVIVOR], cid, 2))
  4322. return PLUGIN_HANDLED;
  4323. }
  4324. else
  4325. {
  4326. // Make Survivor
  4327. if (!cmd_access(id, g_access_flag[ACCESS_MAKE_SURVIVOR], cid, 2))
  4328. return PLUGIN_HANDLED;
  4329. }
  4330.  
  4331. // Retrieve arguments
  4332. static arg[32], player
  4333. read_argv(1, arg, charsmax(arg))
  4334. player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
  4335.  
  4336. // Invalid target
  4337. if (!player) return PLUGIN_HANDLED;
  4338.  
  4339. // Target not allowed to be survivor
  4340. if (!allowed_survivor(player))
  4341. {
  4342. client_print(id, print_console, "[Zombie Arena] %L", id, "CMD_NOT")
  4343. return PLUGIN_HANDLED;
  4344. }
  4345.  
  4346. command_survivor(id, player)
  4347.  
  4348. return PLUGIN_HANDLED;
  4349. }
  4350.  
  4351. // zp_nemesis [target]
  4352. public cmd_nemesis(id, level, cid)
  4353. {
  4354. // Check for access flag depending on the resulting action
  4355. if (g_newround)
  4356. {
  4357. // Start Mode Nemesis
  4358. if (!cmd_access(id, g_access_flag[ACCESS_MODE_NEMESIS], cid, 2))
  4359. return PLUGIN_HANDLED;
  4360. }
  4361. else
  4362. {
  4363. // Make Nemesis
  4364. if (!cmd_access(id, g_access_flag[ACCESS_MAKE_NEMESIS], cid, 2))
  4365. return PLUGIN_HANDLED;
  4366. }
  4367.  
  4368. // Retrieve arguments
  4369. static arg[32], player
  4370. read_argv(1, arg, charsmax(arg))
  4371. player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
  4372.  
  4373. // Invalid target
  4374. if (!player) return PLUGIN_HANDLED;
  4375.  
  4376. // Target not allowed to be nemesis
  4377. if (!allowed_nemesis(player))
  4378. {
  4379. client_print(id, print_console, "[Zombie Arena] %L", id, "CMD_NOT")
  4380. return PLUGIN_HANDLED;
  4381. }
  4382.  
  4383. command_nemesis(id, player)
  4384.  
  4385. return PLUGIN_HANDLED;
  4386. }
  4387.  
  4388. // zp_respawn [target]
  4389. public cmd_respawn(id, level, cid)
  4390. {
  4391. // Check for access flag - Respawn
  4392. if (!cmd_access(id, g_access_flag[ACCESS_RESPAWN_PLAYERS], cid, 2))
  4393. return PLUGIN_HANDLED;
  4394.  
  4395. // Retrieve arguments
  4396. static arg[32], player
  4397. read_argv(1, arg, charsmax(arg))
  4398. player = cmd_target(id, arg, CMDTARGET_ALLOW_SELF)
  4399.  
  4400. // Invalid target
  4401. if (!player) return PLUGIN_HANDLED;
  4402.  
  4403. // Target not allowed to be respawned
  4404. if (!allowed_respawn(player))
  4405. {
  4406. client_print(id, print_console, "[Zombie Arena] %L", id, "CMD_NOT")
  4407. return PLUGIN_HANDLED;
  4408. }
  4409.  
  4410. command_respawn(id, player)
  4411.  
  4412. return PLUGIN_HANDLED;
  4413. }
  4414.  
  4415. // zp_swarm
  4416. public cmd_swarm(id, level, cid)
  4417. {
  4418. // Check for access flag - Mode Swarm
  4419. if (!cmd_access(id, g_access_flag[ACCESS_MODE_SWARM], cid, 2))
  4420. return PLUGIN_HANDLED;
  4421.  
  4422. // Swarm mode not allowed
  4423. if (!allowed_swarm())
  4424. {
  4425. client_print(id, print_console, "[Zombie Arena] %L", id, "CMD_NOT")
  4426. return PLUGIN_HANDLED;
  4427. }
  4428.  
  4429. command_swarm(id)
  4430.  
  4431. return PLUGIN_HANDLED;
  4432. }
  4433.  
  4434. // zp_multi
  4435. public cmd_multi(id, level, cid)
  4436. {
  4437. // Check for access flag - Mode Multi
  4438. if (!cmd_access(id, g_access_flag[ACCESS_MODE_MULTI], cid, 2))
  4439. return PLUGIN_HANDLED;
  4440.  
  4441. // Multi infection mode not allowed
  4442. if (!allowed_multi())
  4443. {
  4444. client_print(id, print_console, "[Zombie Arena] %L", id, "CMD_NOT")
  4445. return PLUGIN_HANDLED;
  4446. }
  4447.  
  4448. command_multi(id)
  4449.  
  4450. return PLUGIN_HANDLED;
  4451. }
  4452.  
  4453. // zp_plague
  4454. public cmd_plague(id, level, cid)
  4455. {
  4456. // Check for access flag - Mode Plague
  4457. if (!cmd_access(id, g_access_flag[ACCESS_MODE_PLAGUE], cid, 2))
  4458. return PLUGIN_HANDLED;
  4459.  
  4460. // Plague mode not allowed
  4461. if (!allowed_plague())
  4462. {
  4463. client_print(id, print_console, "[Zombie Arena] %L", id, "CMD_NOT")
  4464. return PLUGIN_HANDLED;
  4465. }
  4466.  
  4467. command_plague(id)
  4468.  
  4469. return PLUGIN_HANDLED;
  4470. }
  4471.  
  4472. /*================================================================================
  4473. [Message Hooks]
  4474. =================================================================================*/
  4475.  
  4476. // Current Weapon info
  4477. public message_cur_weapon(msg_id, msg_dest, msg_entity)
  4478. {
  4479. // Not alive or zombie
  4480. if (!g_isalive[msg_entity] || g_zombie[msg_entity])
  4481. return;
  4482.  
  4483. // Not an active weapon
  4484. if (get_msg_arg_int(1) != 1)
  4485. return;
  4486.  
  4487. // Unlimited clip disabled for class
  4488. if (g_survivor[msg_entity] ? get_pcvar_num(cvar_survinfammo) <= 1 : get_pcvar_num(cvar_infammo) <= 1)
  4489. return;
  4490.  
  4491. // Get weapon's id
  4492. static weapon
  4493. weapon = get_msg_arg_int(2)
  4494.  
  4495. // Unlimited Clip Ammo for this weapon?
  4496. if (MAXBPAMMO[weapon] > 2)
  4497. {
  4498. // Max out clip ammo
  4499. cs_set_weapon_ammo(fm_cs_get_current_weapon_ent(msg_entity), MAXCLIP[weapon])
  4500.  
  4501. // HUD should show full clip all the time
  4502. set_msg_arg_int(3, get_msg_argtype(3), MAXCLIP[weapon])
  4503. }
  4504. }
  4505.  
  4506. // Take off player's money
  4507. public message_money(msg_id, msg_dest, msg_entity)
  4508. {
  4509. // Remove money setting enabled?
  4510. if (!get_pcvar_num(cvar_removemoney))
  4511. return PLUGIN_CONTINUE;
  4512.  
  4513. fm_cs_set_user_money(msg_entity, 0)
  4514. return PLUGIN_HANDLED;
  4515. }
  4516.  
  4517. // Fix for the HL engine bug when HP is multiples of 256
  4518. public message_health(msg_id, msg_dest, msg_entity)
  4519. {
  4520. // Get player's health
  4521. static health
  4522. health = get_msg_arg_int(1)
  4523.  
  4524. // Don't bother
  4525. if (health < 256) return;
  4526.  
  4527. // Check if we need to fix it
  4528. if (health % 256 == 0)
  4529. fm_set_user_health(msg_entity, pev(msg_entity, pev_health) + 1)
  4530.  
  4531. // HUD can only show as much as 255 hp
  4532. set_msg_arg_int(1, get_msg_argtype(1), 255)
  4533. }
  4534.  
  4535. // Block flashlight battery messages if custom flashlight is enabled instead
  4536. public message_flashbat()
  4537. {
  4538. if (g_cached_customflash)
  4539. return PLUGIN_HANDLED;
  4540.  
  4541. return PLUGIN_CONTINUE;
  4542. }
  4543.  
  4544. // Flashbangs should only affect zombies
  4545. public message_screenfade(msg_id, msg_dest, msg_entity)
  4546. {
  4547. if (get_msg_arg_int(4) != 255 || get_msg_arg_int(5) != 255 || get_msg_arg_int(6) != 255 || get_msg_arg_int(7) < 200)
  4548. return PLUGIN_CONTINUE;
  4549.  
  4550. // Nemesis shouldn't be FBed
  4551. if (g_zombie[msg_entity] && !g_nemesis[msg_entity])
  4552. {
  4553. // Set flash color to nighvision's
  4554. set_msg_arg_int(4, get_msg_argtype(4), get_pcvar_num(cvar_nvgcolor[0]))
  4555. set_msg_arg_int(5, get_msg_argtype(5), get_pcvar_num(cvar_nvgcolor[1]))
  4556. set_msg_arg_int(6, get_msg_argtype(6), get_pcvar_num(cvar_nvgcolor[2]))
  4557. return PLUGIN_CONTINUE;
  4558. }
  4559.  
  4560. return PLUGIN_HANDLED;
  4561. }
  4562.  
  4563. // Prevent spectators' nightvision from being turned off when switching targets, etc.
  4564. public message_nvgtoggle()
  4565. {
  4566. return PLUGIN_HANDLED;
  4567. }
  4568.  
  4569. // Set correct model on player corpses
  4570. public message_clcorpse()
  4571. {
  4572. set_msg_arg_string(1, g_playermodel[get_msg_arg_int(12)])
  4573. }
  4574.  
  4575. // Prevent zombies from seeing any weapon pickup icon
  4576. public message_weappickup(msg_id, msg_dest, msg_entity)
  4577. {
  4578. if (g_zombie[msg_entity])
  4579. return PLUGIN_HANDLED;
  4580.  
  4581. return PLUGIN_CONTINUE;
  4582. }
  4583.  
  4584. // Prevent zombies from seeing any ammo pickup icon
  4585. public message_ammopickup(msg_id, msg_dest, msg_entity)
  4586. {
  4587. if (g_zombie[msg_entity])
  4588. return PLUGIN_HANDLED;
  4589.  
  4590. return PLUGIN_CONTINUE;
  4591. }
  4592.  
  4593. // Block hostage HUD display
  4594. public message_scenario()
  4595. {
  4596. if (get_msg_args() > 1)
  4597. {
  4598. static sprite[8]
  4599. get_msg_arg_string(2, sprite, charsmax(sprite))
  4600.  
  4601. if (equal(sprite, "hostage"))
  4602. return PLUGIN_HANDLED;
  4603. }
  4604.  
  4605. return PLUGIN_CONTINUE;
  4606. }
  4607.  
  4608. // Block hostages from appearing on radar
  4609. public message_hostagepos()
  4610. {
  4611. return PLUGIN_HANDLED;
  4612. }
  4613.  
  4614. // Block some text messages
  4615. public message_textmsg()
  4616. {
  4617. static textmsg[22]
  4618. get_msg_arg_string(2, textmsg, charsmax(textmsg))
  4619.  
  4620. // Game restarting, reset scores and call round end to balance the teams
  4621. if (equal(textmsg, "#Game_will_restart_in"))
  4622. {
  4623. g_scorehumans = 0
  4624. g_scorezombies = 0
  4625. logevent_round_end()
  4626. }
  4627. // Block round end related messages
  4628. else if (equal(textmsg, "#Hostages_Not_Rescued") || equal(textmsg, "#Round_Draw") || equal(textmsg, "#Terrorists_Win") || equal(textmsg, "#CTs_Win"))
  4629. {
  4630. return PLUGIN_HANDLED;
  4631. }
  4632.  
  4633. return PLUGIN_CONTINUE;
  4634. }
  4635.  
  4636. // Block CS round win audio messages, since we're playing our own instead
  4637. public message_sendaudio()
  4638. {
  4639. static audio[17]
  4640. get_msg_arg_string(2, audio, charsmax(audio))
  4641.  
  4642. if(equal(audio[7], "terwin") || equal(audio[7], "ctwin") || equal(audio[7], "rounddraw"))
  4643. return PLUGIN_HANDLED;
  4644.  
  4645. return PLUGIN_CONTINUE;
  4646. }
  4647.  
  4648. // Send actual team scores (T = zombies // CT = humans)
  4649. public message_teamscore()
  4650. {
  4651. static team[2]
  4652. get_msg_arg_string(1, team, charsmax(team))
  4653.  
  4654. switch (team[0])
  4655. {
  4656. // CT
  4657. case 'C': set_msg_arg_int(2, get_msg_argtype(2), g_scorehumans)
  4658. // Terrorist
  4659. case 'T': set_msg_arg_int(2, get_msg_argtype(2), g_scorezombies)
  4660. }
  4661. }
  4662.  
  4663. // Team Switch (or player joining a team for first time)
  4664. public message_teaminfo(msg_id, msg_dest)
  4665. {
  4666. // Only hook global messages
  4667. if (msg_dest != MSG_ALL && msg_dest != MSG_BROADCAST) return;
  4668.  
  4669. // Don't pick up our own TeamInfo messages for this player (bugfix)
  4670. if (g_switchingteam) return;
  4671.  
  4672. // Get player's id
  4673. static id
  4674. id = get_msg_arg_int(1)
  4675.  
  4676. // Enable spectators' nightvision if not spawning right away
  4677. set_task(0.2, "spec_nvision", id)
  4678.  
  4679. // Round didn't start yet, nothing to worry about
  4680. if (g_newround) return;
  4681.  
  4682. // Get his new team
  4683. static team[2]
  4684. get_msg_arg_string(2, team, charsmax(team))
  4685.  
  4686. // Perform some checks to see if they should join a different team instead
  4687. switch (team[0])
  4688. {
  4689. case 'C': // CT
  4690. {
  4691. if (g_survround && fnGetHumans()) // survivor alive --> switch to T and spawn as zombie
  4692. {
  4693. g_respawn_as_zombie[id] = true;
  4694. remove_task(id+TASK_TEAM)
  4695. fm_cs_set_user_team(id, FM_CS_TEAM_T)
  4696. set_msg_arg_string(2, "TERRORIST")
  4697. }
  4698. else if (!fnGetZombies()) // no zombies alive --> switch to T and spawn as zombie
  4699. {
  4700. g_respawn_as_zombie[id] = true;
  4701. remove_task(id+TASK_TEAM)
  4702. fm_cs_set_user_team(id, FM_CS_TEAM_T)
  4703. set_msg_arg_string(2, "TERRORIST")
  4704. }
  4705. }
  4706. case 'T': // Terrorist
  4707. {
  4708. if ((g_swarmround || g_survround) && fnGetHumans()) // survivor alive or swarm round w/ humans --> spawn as zombie
  4709. {
  4710. g_respawn_as_zombie[id] = true;
  4711. }
  4712. else if (fnGetZombies()) // zombies alive --> switch to CT
  4713. {
  4714. remove_task(id+TASK_TEAM)
  4715. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  4716. set_msg_arg_string(2, "CT")
  4717. }
  4718. }
  4719. }
  4720. }
  4721.  
  4722. /*================================================================================
  4723. [Main Functions]
  4724. =================================================================================*/
  4725.  
  4726. // Make Zombie Task
  4727. public make_zombie_task()
  4728. {
  4729. // Call make a zombie with no specific mode
  4730. make_a_zombie(MODE_NONE, 0)
  4731. }
  4732.  
  4733. // Make a Zombie Function
  4734. make_a_zombie(mode, id)
  4735. {
  4736. // Get alive players count
  4737. static iPlayersnum
  4738. iPlayersnum = fnGetAlive()
  4739.  
  4740. // Not enough players, come back later!
  4741. if (iPlayersnum < 1)
  4742. {
  4743. set_task(2.0, "make_zombie_task", TASK_MAKEZOMBIE)
  4744. return;
  4745. }
  4746.  
  4747. // Round started!
  4748. g_newround = false
  4749.  
  4750. // Set up some common vars
  4751. static forward_id, sound[64], iZombies, iMaxZombies
  4752.  
  4753. if ((mode == MODE_NONE && (!get_pcvar_num(cvar_preventconsecutive) || g_lastmode != MODE_SURVIVOR) && random_num(1, get_pcvar_num(cvar_survchance)) == get_pcvar_num(cvar_surv) && iPlayersnum >= get_pcvar_num(cvar_survminplayers)) || mode == MODE_SURVIVOR)
  4754. {
  4755. // Survivor Mode
  4756. g_survround = true
  4757. g_lastmode = MODE_SURVIVOR
  4758.  
  4759. // Choose player randomly?
  4760. if (mode == MODE_NONE)
  4761. id = fnGetRandomAlive(random_num(1, iPlayersnum))
  4762.  
  4763. // Remember id for calling our forward later
  4764. forward_id = id
  4765.  
  4766. // Turn player into a survivor
  4767. humanme(id, 1, 0)
  4768.  
  4769. // Turn the remaining players into zombies
  4770. for (id = 1; id <= g_maxplayers; id++)
  4771. {
  4772. // Not alive
  4773. if (!g_isalive[id])
  4774. continue;
  4775.  
  4776. // Survivor or already a zombie
  4777. if (g_survivor[id] || g_zombie[id])
  4778. continue;
  4779.  
  4780. // Turn into a zombie
  4781. zombieme(id, 0, 0, 1, 0)
  4782. }
  4783.  
  4784. // Play survivor sound
  4785. ArrayGetString(sound_survivor, random_num(0, ArraySize(sound_survivor) - 1), sound, charsmax(sound))
  4786. PlaySound(sound);
  4787.  
  4788. // Show Survivor HUD notice
  4789. set_hudmessage(20, 20, 255, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
  4790. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_SURVIVOR", g_playername[forward_id])
  4791.  
  4792. // Mode fully started!
  4793. g_modestarted = true
  4794.  
  4795. // Round start forward
  4796. ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_SURVIVOR, forward_id);
  4797. }
  4798. else if ((mode == MODE_NONE && (!get_pcvar_num(cvar_preventconsecutive) || g_lastmode != MODE_SWARM) && random_num(1, get_pcvar_num(cvar_swarmchance)) == get_pcvar_num(cvar_swarm) && iPlayersnum >= get_pcvar_num(cvar_swarmminplayers)) || mode == MODE_SWARM)
  4799. {
  4800. // Swarm Mode
  4801. g_swarmround = true
  4802. g_lastmode = MODE_SWARM
  4803.  
  4804. // Make sure there are alive players on both teams (BUGFIX)
  4805. if (!fnGetAliveTs())
  4806. {
  4807. // Move random player to T team
  4808. id = fnGetRandomAlive(random_num(1, iPlayersnum))
  4809. remove_task(id+TASK_TEAM)
  4810. fm_cs_set_user_team(id, FM_CS_TEAM_T)
  4811. fm_user_team_update(id)
  4812. }
  4813. else if (!fnGetAliveCTs())
  4814. {
  4815. // Move random player to CT team
  4816. id = fnGetRandomAlive(random_num(1, iPlayersnum))
  4817. remove_task(id+TASK_TEAM)
  4818. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  4819. fm_user_team_update(id)
  4820. }
  4821.  
  4822. // Turn every T into a zombie
  4823. for (id = 1; id <= g_maxplayers; id++)
  4824. {
  4825. // Not alive
  4826. if (!g_isalive[id])
  4827. continue;
  4828.  
  4829. // Not a Terrorist
  4830. if (fm_cs_get_user_team(id) != FM_CS_TEAM_T)
  4831. continue;
  4832.  
  4833. // Turn into a zombie
  4834. zombieme(id, 0, 0, 1, 0)
  4835. }
  4836.  
  4837. // Play swarm sound
  4838. ArrayGetString(sound_swarm, random_num(0, ArraySize(sound_swarm) - 1), sound, charsmax(sound))
  4839. PlaySound(sound);
  4840.  
  4841. // Show Swarm HUD notice
  4842. set_hudmessage(20, 255, 20, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
  4843. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_SWARM")
  4844.  
  4845. // Mode fully started!
  4846. g_modestarted = true
  4847.  
  4848. // Round start forward
  4849. ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_SWARM, 0);
  4850. }
  4851. else if ((mode == MODE_NONE && (!get_pcvar_num(cvar_preventconsecutive) || g_lastmode != MODE_MULTI) && random_num(1, get_pcvar_num(cvar_multichance)) == get_pcvar_num(cvar_multi) && floatround(iPlayersnum*get_pcvar_float(cvar_multiratio), floatround_ceil) >= 2 && floatround(iPlayersnum*get_pcvar_float(cvar_multiratio), floatround_ceil) < iPlayersnum && iPlayersnum >= get_pcvar_num(cvar_multiminplayers)) || mode == MODE_MULTI)
  4852. {
  4853. // Multi Infection Mode
  4854. g_lastmode = MODE_MULTI
  4855.  
  4856. // iMaxZombies is rounded up, in case there aren't enough players
  4857. iMaxZombies = floatround(iPlayersnum*get_pcvar_float(cvar_multiratio), floatround_ceil)
  4858. iZombies = 0
  4859.  
  4860. // Randomly turn iMaxZombies players into zombies
  4861. while (iZombies < iMaxZombies)
  4862. {
  4863. // Keep looping through all players
  4864. if (++id > g_maxplayers) id = 1
  4865.  
  4866. // Dead or already a zombie
  4867. if (!g_isalive[id] || g_zombie[id])
  4868. continue;
  4869.  
  4870. // Random chance
  4871. if (random_num(0, 1))
  4872. {
  4873. // Turn into a zombie
  4874. zombieme(id, 0, 0, 1, 0)
  4875. iZombies++
  4876. }
  4877. }
  4878.  
  4879. // Turn the remaining players into humans
  4880. for (id = 1; id <= g_maxplayers; id++)
  4881. {
  4882. // Only those of them who aren't zombies
  4883. if (!g_isalive[id] || g_zombie[id])
  4884. continue;
  4885.  
  4886. // Switch to CT
  4887. if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
  4888. {
  4889. remove_task(id+TASK_TEAM)
  4890. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  4891. fm_user_team_update(id)
  4892. }
  4893. }
  4894.  
  4895. // Play multi infection sound
  4896. ArrayGetString(sound_multi, random_num(0, ArraySize(sound_multi) - 1), sound, charsmax(sound))
  4897. PlaySound(sound);
  4898.  
  4899. // Show Multi Infection HUD notice
  4900. set_hudmessage(200, 50, 0, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
  4901. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_MULTI")
  4902.  
  4903. // Mode fully started!
  4904. g_modestarted = true
  4905.  
  4906. // Round start forward
  4907. ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_MULTI, 0);
  4908. }
  4909. else if ((mode == MODE_NONE && (!get_pcvar_num(cvar_preventconsecutive) || g_lastmode != MODE_PLAGUE) && random_num(1, get_pcvar_num(cvar_plaguechance)) == get_pcvar_num(cvar_plague) && floatround((iPlayersnum-(get_pcvar_num(cvar_plaguenemnum)+get_pcvar_num(cvar_plaguesurvnum)))*get_pcvar_float(cvar_plagueratio), floatround_ceil) >= 1
  4910. && iPlayersnum-(get_pcvar_num(cvar_plaguesurvnum)+get_pcvar_num(cvar_plaguenemnum)+floatround((iPlayersnum-(get_pcvar_num(cvar_plaguenemnum)+get_pcvar_num(cvar_plaguesurvnum)))*get_pcvar_float(cvar_plagueratio), floatround_ceil)) >= 1 && iPlayersnum >= get_pcvar_num(cvar_plagueminplayers)) || mode == MODE_PLAGUE)
  4911. {
  4912. // Plague Mode
  4913. g_plagueround = true
  4914. g_lastmode = MODE_PLAGUE
  4915.  
  4916. // Turn specified amount of players into Survivors
  4917. static iSurvivors, iMaxSurvivors
  4918. iMaxSurvivors = get_pcvar_num(cvar_plaguesurvnum)
  4919. iSurvivors = 0
  4920.  
  4921. while (iSurvivors < iMaxSurvivors)
  4922. {
  4923. // Choose random guy
  4924. id = fnGetRandomAlive(random_num(1, iPlayersnum))
  4925.  
  4926. // Already a survivor?
  4927. if (g_survivor[id])
  4928. continue;
  4929.  
  4930. // If not, turn him into one
  4931. humanme(id, 1, 0)
  4932. iSurvivors++
  4933.  
  4934. // Apply survivor health multiplier
  4935. fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_plaguesurvhpmulti)))
  4936. }
  4937.  
  4938. // Turn specified amount of players into Nemesis
  4939. static iNemesis, iMaxNemesis
  4940. iMaxNemesis = get_pcvar_num(cvar_plaguenemnum)
  4941. iNemesis = 0
  4942.  
  4943. while (iNemesis < iMaxNemesis)
  4944. {
  4945. // Choose random guy
  4946. id = fnGetRandomAlive(random_num(1, iPlayersnum))
  4947.  
  4948. // Already a survivor or nemesis?
  4949. if (g_survivor[id] || g_nemesis[id])
  4950. continue;
  4951.  
  4952. // If not, turn him into one
  4953. zombieme(id, 0, 1, 0, 0)
  4954. iNemesis++
  4955.  
  4956. // Apply nemesis health multiplier
  4957. fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_plaguenemhpmulti)))
  4958. }
  4959.  
  4960. // iMaxZombies is rounded up, in case there aren't enough players
  4961. iMaxZombies = floatround((iPlayersnum-(get_pcvar_num(cvar_plaguenemnum)+get_pcvar_num(cvar_plaguesurvnum)))*get_pcvar_float(cvar_plagueratio), floatround_ceil)
  4962. iZombies = 0
  4963.  
  4964. // Randomly turn iMaxZombies players into zombies
  4965. while (iZombies < iMaxZombies)
  4966. {
  4967. // Keep looping through all players
  4968. if (++id > g_maxplayers) id = 1
  4969.  
  4970. // Dead or already a zombie or survivor
  4971. if (!g_isalive[id] || g_zombie[id] || g_survivor[id])
  4972. continue;
  4973.  
  4974. // Random chance
  4975. if (random_num(0, 1))
  4976. {
  4977. // Turn into a zombie
  4978. zombieme(id, 0, 0, 1, 0)
  4979. iZombies++
  4980. }
  4981. }
  4982.  
  4983. // Turn the remaining players into humans
  4984. for (id = 1; id <= g_maxplayers; id++)
  4985. {
  4986. // Only those of them who arent zombies or survivor
  4987. if (!g_isalive[id] || g_zombie[id] || g_survivor[id])
  4988. continue;
  4989.  
  4990. // Switch to CT
  4991. if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
  4992. {
  4993. remove_task(id+TASK_TEAM)
  4994. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  4995. fm_user_team_update(id)
  4996. }
  4997. }
  4998.  
  4999. // Play plague sound
  5000. ArrayGetString(sound_plague, random_num(0, ArraySize(sound_plague) - 1), sound, charsmax(sound))
  5001. PlaySound(sound);
  5002.  
  5003. // Show Plague HUD notice
  5004. set_hudmessage(0, 50, 200, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
  5005. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_PLAGUE")
  5006.  
  5007. // Mode fully started!
  5008. g_modestarted = true
  5009.  
  5010. // Round start forward
  5011. ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_PLAGUE, 0);
  5012. }
  5013. else
  5014. {
  5015. // Single Infection Mode or Nemesis Mode
  5016.  
  5017. // Choose player randomly?
  5018. if (mode == MODE_NONE)
  5019. id = fnGetRandomAlive(random_num(1, iPlayersnum))
  5020.  
  5021. // Remember id for calling our forward later
  5022. forward_id = id
  5023.  
  5024. if ((mode == MODE_NONE && (!get_pcvar_num(cvar_preventconsecutive) || g_lastmode != MODE_NEMESIS) && random_num(1, get_pcvar_num(cvar_nemchance)) == get_pcvar_num(cvar_nem) && iPlayersnum >= get_pcvar_num(cvar_nemminplayers)) || mode == MODE_NEMESIS)
  5025. {
  5026. // Nemesis Mode
  5027. g_nemround = true
  5028. g_lastmode = MODE_NEMESIS
  5029.  
  5030. // Turn player into nemesis
  5031. zombieme(id, 0, 1, 0, 0)
  5032. }
  5033. else
  5034. {
  5035. // Single Infection Mode
  5036. g_lastmode = MODE_INFECTION
  5037.  
  5038. // Turn player into the first zombie
  5039. zombieme(id, 0, 0, 0, 0)
  5040. }
  5041.  
  5042. // Remaining players should be humans (CTs)
  5043. for (id = 1; id <= g_maxplayers; id++)
  5044. {
  5045. // Not alive
  5046. if (!g_isalive[id])
  5047. continue;
  5048.  
  5049. // First zombie/nemesis
  5050. if (g_zombie[id])
  5051. continue;
  5052.  
  5053. // Switch to CT
  5054. if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
  5055. {
  5056. remove_task(id+TASK_TEAM)
  5057. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  5058. fm_user_team_update(id)
  5059. }
  5060. }
  5061.  
  5062. if (g_nemround)
  5063. {
  5064. // Play Nemesis sound
  5065. ArrayGetString(sound_nemesis, random_num(0, ArraySize(sound_nemesis) - 1), sound, charsmax(sound))
  5066. PlaySound(sound);
  5067.  
  5068. // Show Nemesis HUD notice
  5069. set_hudmessage(255, 20, 20, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
  5070. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_NEMESIS", g_playername[forward_id])
  5071.  
  5072. // Mode fully started!
  5073. g_modestarted = true
  5074.  
  5075. // Round start forward
  5076. ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_NEMESIS, forward_id);
  5077. }
  5078. else
  5079. {
  5080. // Show First Zombie HUD notice
  5081. set_hudmessage(255, 0, 0, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 5.0, 1.0, 1.0, -1)
  5082. ShowSyncHudMsg(0, g_MsgSync, "%L",LANG_PLAYER, "NOTICE_FIRST", g_playername[forward_id])
  5083.  
  5084. // Mode fully started!
  5085. g_modestarted = true
  5086.  
  5087. // Round start forward
  5088. ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_INFECTION, forward_id);
  5089. }
  5090. }
  5091.  
  5092. // Start ambience sounds after a mode begins
  5093. if ((g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] && g_nemround) || (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] && g_survround) || (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] && g_swarmround) || (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] && g_plagueround) || (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] && !g_nemround && !g_survround && !g_swarmround && !g_plagueround))
  5094. {
  5095. remove_task(TASK_AMBIENCESOUNDS)
  5096. set_task(2.0, "ambience_sound_effects", TASK_AMBIENCESOUNDS)
  5097. }
  5098. }
  5099.  
  5100. // Zombie Me Function (player id, infector, turn into a nemesis, silent mode, deathmsg and rewards)
  5101. zombieme(id, infector, nemesis, silentmode, rewards)
  5102. {
  5103. // User infect attempt forward
  5104. ExecuteForward(g_fwUserInfect_attempt, g_fwDummyResult, id, infector, nemesis)
  5105.  
  5106. // One or more plugins blocked the infection. Only allow this after making sure it's
  5107. // not going to leave us with no zombies. Take into account a last player leaving case.
  5108. // BUGFIX: only allow after a mode has started, to prevent blocking first zombie e.g.
  5109. if (g_fwDummyResult >= ZP_PLUGIN_HANDLED && g_modestarted && fnGetZombies() > g_lastplayerleaving)
  5110. return;
  5111.  
  5112. // Pre user infect forward
  5113. ExecuteForward(g_fwUserInfected_pre, g_fwDummyResult, id, infector, nemesis)
  5114.  
  5115. // Show zombie class menu if they haven't chosen any (e.g. just connected)
  5116. if (g_zombieclassnext[id] == ZCLASS_NONE && get_pcvar_num(cvar_zclasses))
  5117. set_task(0.2, "show_menu_zclass", id)
  5118.  
  5119. // Set selected zombie class
  5120. g_zombieclass[id] = g_zombieclassnext[id]
  5121. // If no class selected yet, use the first (default) one
  5122. if (g_zombieclass[id] == ZCLASS_NONE) g_zombieclass[id] = 0
  5123.  
  5124. // Way to go...
  5125. g_zombie[id] = true
  5126. g_nemesis[id] = false
  5127. g_survivor[id] = false
  5128. g_firstzombie[id] = false
  5129.  
  5130. // Remove survivor's aura (bugfix)
  5131. set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_BRIGHTLIGHT)
  5132.  
  5133. // Remove spawn protection (bugfix)
  5134. g_nodamage[id] = false
  5135. set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_NODRAW)
  5136.  
  5137. // Reset burning duration counter (bugfix)
  5138. g_burning_duration[id] = 0
  5139.  
  5140. // Show deathmsg and reward infector?
  5141. if (rewards && infector)
  5142. {
  5143. // Send death notice and fix the "dead" attrib on scoreboard
  5144. SendDeathMsg(infector, id)
  5145. FixDeadAttrib(id)
  5146.  
  5147. // Reward frags, deaths, health, and ammo packs
  5148. UpdateFrags(infector, id, get_pcvar_num(cvar_fragsinfect), 1, 1)
  5149. g_ammopacks[infector] += get_pcvar_num(cvar_ammoinfect)
  5150. fm_set_user_health(infector, pev(infector, pev_health) + get_pcvar_num(cvar_zombiebonushp))
  5151. }
  5152.  
  5153. // Cache speed, knockback, and name for player's class
  5154. g_zombie_spd[id] = float(ArrayGetCell(g_zclass_spd, g_zombieclass[id]))
  5155. g_zombie_knockback[id] = Float:ArrayGetCell(g_zclass_kb, g_zombieclass[id])
  5156. ArrayGetString(g_zclass_name, g_zombieclass[id], g_zombie_classname[id], charsmax(g_zombie_classname[]))
  5157.  
  5158. // Set zombie attributes based on the mode
  5159. static sound[64]
  5160. if (!silentmode)
  5161. {
  5162. if (nemesis)
  5163. {
  5164. // Nemesis
  5165. g_nemesis[id] = true
  5166.  
  5167. // Set health [0 = auto]
  5168. if (get_pcvar_num(cvar_nemhp) == 0)
  5169. {
  5170. if (get_pcvar_num(cvar_nembasehp) == 0)
  5171. fm_set_user_health(id, ArrayGetCell(g_zclass_hp, 0) * fnGetAlive())
  5172. else
  5173. fm_set_user_health(id, get_pcvar_num(cvar_nembasehp) * fnGetAlive())
  5174. }
  5175. else
  5176. fm_set_user_health(id, get_pcvar_num(cvar_nemhp))
  5177.  
  5178. // Set gravity, unless frozen
  5179. if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_nemgravity))
  5180. }
  5181. else if (fnGetZombies() == 1)
  5182. {
  5183. // First zombie
  5184. g_firstzombie[id] = true
  5185.  
  5186. // Set health and gravity, unless frozen
  5187. fm_set_user_health(id, floatround(float(ArrayGetCell(g_zclass_hp, g_zombieclass[id])) * get_pcvar_float(cvar_zombiefirsthp)))
  5188. if (!g_frozen[id]) set_pev(id, pev_gravity, Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id]))
  5189.  
  5190. // Infection sound
  5191. ArrayGetString(zombie_infect, random_num(0, ArraySize(zombie_infect) - 1), sound, charsmax(sound))
  5192. emit_sound(id, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  5193. }
  5194. else
  5195. {
  5196. // Infected by someone
  5197.  
  5198. // Set health and gravity, unless frozen
  5199. fm_set_user_health(id, ArrayGetCell(g_zclass_hp, g_zombieclass[id]))
  5200. if (!g_frozen[id]) set_pev(id, pev_gravity, Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id]))
  5201.  
  5202. // Infection sound
  5203. ArrayGetString(zombie_infect, random_num(0, ArraySize(zombie_infect) - 1), sound, charsmax(sound))
  5204. emit_sound(id, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  5205.  
  5206. // Show Infection HUD notice
  5207. set_hudmessage(255, 0, 0, HUD_INFECT_X, HUD_INFECT_Y, 0, 0.0, 5.0, 1.0, 1.0, -1)
  5208.  
  5209. if (infector) // infected by someone?
  5210. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_INFECT2", g_playername[id], g_playername[infector])
  5211. else
  5212. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_INFECT", g_playername[id])
  5213. }
  5214. }
  5215. else
  5216. {
  5217. // Silent mode, no HUD messages, no infection sounds
  5218.  
  5219. // Set health and gravity, unless frozen
  5220. fm_set_user_health(id, ArrayGetCell(g_zclass_hp, g_zombieclass[id]))
  5221. if (!g_frozen[id]) set_pev(id, pev_gravity, Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id]))
  5222. }
  5223.  
  5224. // Remove previous tasks
  5225. remove_task(id+TASK_MODEL)
  5226. remove_task(id+TASK_BLOOD)
  5227. remove_task(id+TASK_AURA)
  5228. remove_task(id+TASK_BURN)
  5229.  
  5230. // Switch to T
  5231. if (fm_cs_get_user_team(id) != FM_CS_TEAM_T) // need to change team?
  5232. {
  5233. remove_task(id+TASK_TEAM)
  5234. fm_cs_set_user_team(id, FM_CS_TEAM_T)
  5235. fm_user_team_update(id)
  5236. }
  5237.  
  5238. // Custom models stuff
  5239. static currentmodel[32], tempmodel[32], already_has_model, i, iRand, size
  5240. already_has_model = false
  5241.  
  5242. if (g_handle_models_on_separate_ent)
  5243. {
  5244. // Set the right model
  5245. if (g_nemesis[id])
  5246. {
  5247. iRand = random_num(0, ArraySize(model_nemesis) - 1)
  5248. ArrayGetString(model_nemesis, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  5249. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_nemesis, iRand))
  5250. }
  5251. else
  5252. {
  5253. if (get_pcvar_num(cvar_adminmodelszombie) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
  5254. {
  5255. iRand = random_num(0, ArraySize(model_admin_zombie) - 1)
  5256. ArrayGetString(model_admin_zombie, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  5257. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_zombie, iRand))
  5258. }
  5259. else
  5260. {
  5261. iRand = random_num(ArrayGetCell(g_zclass_modelsstart, g_zombieclass[id]), ArrayGetCell(g_zclass_modelsend, g_zombieclass[id]) - 1)
  5262. ArrayGetString(g_zclass_playermodel, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  5263. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_zclass_modelindex, iRand))
  5264. }
  5265. }
  5266.  
  5267. // Set model on player model entity
  5268. fm_set_playermodel_ent(id)
  5269.  
  5270. // Nemesis glow / remove glow on player model entity, unless frozen
  5271. if (!g_frozen[id])
  5272. {
  5273. if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
  5274. fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 255, 0, 0, kRenderNormal, 25)
  5275. else
  5276. fm_set_rendering(g_ent_playermodel[id])
  5277. }
  5278. }
  5279. else
  5280. {
  5281. // Get current model for comparing it with the current one
  5282. fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
  5283.  
  5284. // Set the right model, after checking that we don't already have it
  5285. if (g_nemesis[id])
  5286. {
  5287. size = ArraySize(model_nemesis)
  5288. for (i = 0; i < size; i++)
  5289. {
  5290. ArrayGetString(model_nemesis, i, tempmodel, charsmax(tempmodel))
  5291. if (equal(currentmodel, tempmodel)) already_has_model = true
  5292. }
  5293.  
  5294. if (!already_has_model)
  5295. {
  5296. iRand = random_num(0, size - 1)
  5297. ArrayGetString(model_nemesis, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  5298. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_nemesis, iRand))
  5299. }
  5300. }
  5301. else
  5302. {
  5303. if (get_pcvar_num(cvar_adminmodelszombie) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
  5304. {
  5305. size = ArraySize(model_admin_zombie)
  5306. for (i = 0; i < size; i++)
  5307. {
  5308. ArrayGetString(model_admin_zombie, i, tempmodel, charsmax(tempmodel))
  5309. if (equal(currentmodel, tempmodel)) already_has_model = true
  5310. }
  5311.  
  5312. if (!already_has_model)
  5313. {
  5314. iRand = random_num(0, size - 1)
  5315. ArrayGetString(model_admin_zombie, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  5316. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_zombie, iRand))
  5317. }
  5318. }
  5319. else
  5320. {
  5321. for (i = ArrayGetCell(g_zclass_modelsstart, g_zombieclass[id]); i < ArrayGetCell(g_zclass_modelsend, g_zombieclass[id]); i++)
  5322. {
  5323. ArrayGetString(g_zclass_playermodel, i, tempmodel, charsmax(tempmodel))
  5324. if (equal(currentmodel, tempmodel)) already_has_model = true
  5325. }
  5326.  
  5327. if (!already_has_model)
  5328. {
  5329. iRand = random_num(ArrayGetCell(g_zclass_modelsstart, g_zombieclass[id]), ArrayGetCell(g_zclass_modelsend, g_zombieclass[id]) - 1)
  5330. ArrayGetString(g_zclass_playermodel, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  5331. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_zclass_modelindex, iRand))
  5332. }
  5333. }
  5334. }
  5335.  
  5336. // Need to change the model?
  5337. if (!already_has_model)
  5338. {
  5339. // An additional delay is offset at round start
  5340. // since SVC_BAD is more likely to be triggered there
  5341. if (g_newround)
  5342. set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
  5343. else
  5344. fm_user_model_update(id+TASK_MODEL)
  5345. }
  5346.  
  5347. // Nemesis glow / remove glow, unless frozen
  5348. if (!g_frozen[id])
  5349. {
  5350. if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
  5351. fm_set_rendering(id, kRenderFxGlowShell, 255, 0, 0, kRenderNormal, 25)
  5352. else
  5353. fm_set_rendering(id)
  5354. }
  5355. }
  5356.  
  5357. // Remove any zoom (bugfix)
  5358. cs_set_user_zoom(id, CS_RESET_ZOOM, 1)
  5359.  
  5360. // Remove armor
  5361. set_pev(id, pev_armorvalue, 0.0)
  5362.  
  5363. // Drop weapons when infected
  5364. drop_weapons(id, 1)
  5365. drop_weapons(id, 2)
  5366.  
  5367. // Strip zombies from guns and give them a knife
  5368. fm_strip_user_weapons(id)
  5369. fm_give_item(id, "weapon_knife")
  5370.  
  5371. // Fancy effects
  5372. infection_effects(id)
  5373.  
  5374. // Nemesis aura task
  5375. if (g_nemesis[id] && get_pcvar_num(cvar_nemaura))
  5376. set_task(0.1, "zombie_aura", id+TASK_AURA, _, _, "b")
  5377.  
  5378. // Give Zombies Night Vision?
  5379. if (get_pcvar_num(cvar_nvggive))
  5380. {
  5381. g_nvision[id] = true
  5382.  
  5383. if (!g_isbot[id])
  5384. {
  5385. // Turn on Night Vision automatically?
  5386. if (get_pcvar_num(cvar_nvggive) == 1)
  5387. {
  5388. g_nvisionenabled[id] = true
  5389.  
  5390. // Custom nvg?
  5391. if (get_pcvar_num(cvar_customnvg))
  5392. {
  5393. remove_task(id+TASK_NVISION)
  5394. set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
  5395. }
  5396. else
  5397. set_user_gnvision(id, 1)
  5398. }
  5399. // Turn off nightvision when infected (bugfix)
  5400. else if (g_nvisionenabled[id])
  5401. {
  5402. if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
  5403. else set_user_gnvision(id, 0)
  5404. g_nvisionenabled[id] = false
  5405. }
  5406. }
  5407. else
  5408. cs_set_user_nvg(id, 1); // turn on NVG for bots
  5409. }
  5410. // Disable nightvision when infected (bugfix)
  5411. else if (g_nvision[id])
  5412. {
  5413. if (g_isbot[id]) cs_set_user_nvg(id, 0) // Turn off NVG for bots
  5414. if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
  5415. else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
  5416. g_nvision[id] = false
  5417. g_nvisionenabled[id] = false
  5418. }
  5419.  
  5420. // Set custom FOV?
  5421. if (get_pcvar_num(cvar_zombiefov) != 90 && get_pcvar_num(cvar_zombiefov) != 0)
  5422. {
  5423. message_begin(MSG_ONE, g_msgSetFOV, _, id)
  5424. write_byte(get_pcvar_num(cvar_zombiefov)) // fov angle
  5425. message_end()
  5426. }
  5427.  
  5428. // Call the bloody task
  5429. if (!g_nemesis[id] && get_pcvar_num(cvar_zombiebleeding))
  5430. set_task(0.7, "make_blood", id+TASK_BLOOD, _, _, "b")
  5431.  
  5432. // Idle sounds task
  5433. if (!g_nemesis[id])
  5434. set_task(random_float(50.0, 70.0), "zombie_play_idle", id+TASK_BLOOD, _, _, "b")
  5435.  
  5436. // Turn off zombie's flashlight
  5437. turn_off_flashlight(id)
  5438.  
  5439. // Post user infect forward
  5440. ExecuteForward(g_fwUserInfected_post, g_fwDummyResult, id, infector, nemesis)
  5441.  
  5442. // Last Zombie Check
  5443. fnCheckLastZombie()
  5444. }
  5445.  
  5446. // Function Human Me (player id, turn into a survivor, silent mode)
  5447. humanme(id, survivor, silentmode)
  5448. {
  5449. // User humanize attempt forward
  5450. ExecuteForward(g_fwUserHumanize_attempt, g_fwDummyResult, id, survivor)
  5451.  
  5452. // One or more plugins blocked the "humanization". Only allow this after making sure it's
  5453. // not going to leave us with no humans. Take into account a last player leaving case.
  5454. // BUGFIX: only allow after a mode has started, to prevent blocking first survivor e.g.
  5455. if (g_fwDummyResult >= ZP_PLUGIN_HANDLED && g_modestarted && fnGetHumans() > g_lastplayerleaving)
  5456. return;
  5457.  
  5458. // Pre user humanize forward
  5459. ExecuteForward(g_fwUserHumanized_pre, g_fwDummyResult, id, survivor)
  5460.  
  5461. // Remove previous tasks
  5462. remove_task(id+TASK_MODEL)
  5463. remove_task(id+TASK_BLOOD)
  5464. remove_task(id+TASK_AURA)
  5465. remove_task(id+TASK_BURN)
  5466. remove_task(id+TASK_NVISION)
  5467.  
  5468. // Reset some vars
  5469. g_zombie[id] = false
  5470. g_nemesis[id] = false
  5471. g_survivor[id] = false
  5472. g_firstzombie[id] = false
  5473. g_canbuy[id] = true
  5474. g_nvision[id] = false
  5475. g_nvisionenabled[id] = false
  5476.  
  5477. // Remove survivor's aura (bugfix)
  5478. set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_BRIGHTLIGHT)
  5479.  
  5480. // Remove spawn protection (bugfix)
  5481. g_nodamage[id] = false
  5482. set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_NODRAW)
  5483.  
  5484. // Reset burning duration counter (bugfix)
  5485. g_burning_duration[id] = 0
  5486.  
  5487. // Drop previous weapons
  5488. drop_weapons(id, 1)
  5489. drop_weapons(id, 2)
  5490.  
  5491. // Strip off from weapons
  5492. fm_strip_user_weapons(id)
  5493. fm_give_item(id, "weapon_knife")
  5494.  
  5495. // Set human attributes based on the mode
  5496. if (survivor)
  5497. {
  5498. // Survivor
  5499. g_survivor[id] = true
  5500.  
  5501. // Set Health [0 = auto]
  5502. if (get_pcvar_num(cvar_survhp) == 0)
  5503. {
  5504. if (get_pcvar_num(cvar_survbasehp) == 0)
  5505. fm_set_user_health(id, get_pcvar_num(cvar_humanhp) * fnGetAlive())
  5506. else
  5507. fm_set_user_health(id, get_pcvar_num(cvar_survbasehp) * fnGetAlive())
  5508. }
  5509. else
  5510. fm_set_user_health(id, get_pcvar_num(cvar_survhp))
  5511.  
  5512. // Set gravity, unless frozen
  5513. if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_survgravity))
  5514.  
  5515. // Give survivor his own weapon
  5516. static survweapon[32]
  5517. get_pcvar_string(cvar_survweapon, survweapon, charsmax(survweapon))
  5518. fm_give_item(id, survweapon)
  5519. ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[cs_weapon_name_to_id(survweapon)], AMMOTYPE[cs_weapon_name_to_id(survweapon)], MAXBPAMMO[cs_weapon_name_to_id(survweapon)])
  5520.  
  5521. // Turn off his flashlight
  5522. turn_off_flashlight(id)
  5523.  
  5524. // Give the survivor a bright light
  5525. if (get_pcvar_num(cvar_survaura)) set_pev(id, pev_effects, pev(id, pev_effects) | EF_BRIGHTLIGHT)
  5526.  
  5527. // Survivor bots will also need nightvision to see in the dark
  5528. if (g_isbot[id])
  5529. {
  5530. g_nvision[id] = true
  5531. cs_set_user_nvg(id, 1)
  5532. }
  5533. }
  5534. else
  5535. {
  5536. // Human taking an antidote
  5537.  
  5538. // Set health
  5539. fm_set_user_health(id, get_pcvar_num(cvar_humanhp))
  5540.  
  5541. // Set gravity, unless frozen
  5542. if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_humangravity))
  5543.  
  5544. // Show custom buy menu?
  5545. if (get_pcvar_num(cvar_buycustom))
  5546. set_task(0.2, "show_menu_buy1", id+TASK_SPAWN)
  5547.  
  5548. // Silent mode = no HUD messages, no antidote sound
  5549. if (!silentmode)
  5550. {
  5551. // Antidote sound
  5552. static sound[64]
  5553. ArrayGetString(sound_antidote, random_num(0, ArraySize(sound_antidote) - 1), sound, charsmax(sound))
  5554. emit_sound(id, CHAN_ITEM, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  5555.  
  5556. // Show Antidote HUD notice
  5557. set_hudmessage(0, 0, 255, HUD_INFECT_X, HUD_INFECT_Y, 0, 0.0, 5.0, 1.0, 1.0, -1)
  5558. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_ANTIDOTE", g_playername[id])
  5559. }
  5560. }
  5561.  
  5562. // Switch to CT
  5563. if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
  5564. {
  5565. remove_task(id+TASK_TEAM)
  5566. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  5567. fm_user_team_update(id)
  5568. }
  5569.  
  5570. // Custom models stuff
  5571. static currentmodel[32], tempmodel[32], already_has_model, i, iRand, size
  5572. already_has_model = false
  5573.  
  5574. if (g_handle_models_on_separate_ent)
  5575. {
  5576. // Set the right model
  5577. if (g_survivor[id])
  5578. {
  5579. iRand = random_num(0, ArraySize(model_survivor) - 1)
  5580. ArrayGetString(model_survivor, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  5581. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_survivor, iRand))
  5582. }
  5583. else
  5584. {
  5585. if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
  5586. {
  5587. iRand = random_num(0, ArraySize(model_admin_human) - 1)
  5588. ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  5589. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
  5590. }
  5591. else
  5592. {
  5593. iRand = random_num(0, ArraySize(model_human) - 1)
  5594. ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  5595. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
  5596. }
  5597. }
  5598.  
  5599. // Set model on player model entity
  5600. fm_set_playermodel_ent(id)
  5601.  
  5602. // Set survivor glow / remove glow on player model entity, unless frozen
  5603. if (!g_frozen[id])
  5604. {
  5605. if (g_survivor[id] && get_pcvar_num(cvar_survglow))
  5606. fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
  5607. else
  5608. fm_set_rendering(g_ent_playermodel[id])
  5609. }
  5610. }
  5611. else
  5612. {
  5613. // Get current model for comparing it with the current one
  5614. fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
  5615.  
  5616. // Set the right model, after checking that we don't already have it
  5617. if (g_survivor[id])
  5618. {
  5619. size = ArraySize(model_survivor)
  5620. for (i = 0; i < size; i++)
  5621. {
  5622. ArrayGetString(model_survivor, i, tempmodel, charsmax(tempmodel))
  5623. if (equal(currentmodel, tempmodel)) already_has_model = true
  5624. }
  5625.  
  5626. if (!already_has_model)
  5627. {
  5628. iRand = random_num(0, size - 1)
  5629. ArrayGetString(model_survivor, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  5630. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_survivor, iRand))
  5631. }
  5632. }
  5633. else
  5634. {
  5635. if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
  5636. {
  5637. size = ArraySize(model_admin_human)
  5638. for (i = 0; i < size; i++)
  5639. {
  5640. ArrayGetString(model_admin_human, i, tempmodel, charsmax(tempmodel))
  5641. if (equal(currentmodel, tempmodel)) already_has_model = true
  5642. }
  5643.  
  5644. if (!already_has_model)
  5645. {
  5646. iRand = random_num(0, size - 1)
  5647. ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  5648. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
  5649. }
  5650. }
  5651. else
  5652. {
  5653. size = ArraySize(model_human)
  5654. for (i = 0; i < size; i++)
  5655. {
  5656. ArrayGetString(model_human, i, tempmodel, charsmax(tempmodel))
  5657. if (equal(currentmodel, tempmodel)) already_has_model = true
  5658. }
  5659.  
  5660. if (!already_has_model)
  5661. {
  5662. iRand = random_num(0, size - 1)
  5663. ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  5664. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
  5665. }
  5666. }
  5667. }
  5668.  
  5669. // Need to change the model?
  5670. if (!already_has_model)
  5671. {
  5672. // An additional delay is offset at round start
  5673. // since SVC_BAD is more likely to be triggered there
  5674. if (g_newround)
  5675. set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
  5676. else
  5677. fm_user_model_update(id+TASK_MODEL)
  5678. }
  5679.  
  5680. // Set survivor glow / remove glow, unless frozen
  5681. if (!g_frozen[id])
  5682. {
  5683. if (g_survivor[id] && get_pcvar_num(cvar_survglow))
  5684. fm_set_rendering(id, kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
  5685. else
  5686. fm_set_rendering(id)
  5687. }
  5688. }
  5689.  
  5690. // Restore FOV?
  5691. if (get_pcvar_num(cvar_zombiefov) != 90 && get_pcvar_num(cvar_zombiefov) != 0)
  5692. {
  5693. message_begin(MSG_ONE, g_msgSetFOV, _, id)
  5694. write_byte(90) // angle
  5695. message_end()
  5696. }
  5697.  
  5698. // Disable nightvision
  5699. if (g_isbot[id]) cs_set_user_nvg(id, 0)
  5700. else if (!get_pcvar_num(cvar_customnvg) && g_nvisionenabled[id]) set_user_gnvision(id, 0)
  5701.  
  5702. // Post user humanize forward
  5703. ExecuteForward(g_fwUserHumanized_post, g_fwDummyResult, id, survivor)
  5704.  
  5705. // Last Zombie Check
  5706. fnCheckLastZombie()
  5707. }
  5708.  
  5709. /*================================================================================
  5710. [Other Functions and Tasks]
  5711. =================================================================================*/
  5712.  
  5713. public cache_cvars()
  5714. {
  5715. g_cached_zombiesilent = get_pcvar_num(cvar_zombiesilent)
  5716. g_cached_customflash = get_pcvar_num(cvar_customflash)
  5717. g_cached_humanspd = get_pcvar_float(cvar_humanspd)
  5718. g_cached_nemspd = get_pcvar_float(cvar_nemspd)
  5719. g_cached_survspd = get_pcvar_float(cvar_survspd)
  5720. g_cached_leapzombies = get_pcvar_num(cvar_leapzombies)
  5721. g_cached_leapzombiescooldown = get_pcvar_float(cvar_leapzombiescooldown)
  5722. g_cached_leapnemesis = get_pcvar_num(cvar_leapnemesis)
  5723. g_cached_leapnemesiscooldown = get_pcvar_float(cvar_leapnemesiscooldown)
  5724. g_cached_leapsurvivor = get_pcvar_num(cvar_leapsurvivor)
  5725. g_cached_leapsurvivorcooldown = get_pcvar_float(cvar_leapsurvivorcooldown)
  5726. }
  5727.  
  5728. load_customization_from_files()
  5729. {
  5730. // Build customization file path
  5731. new path[64]
  5732. get_configsdir(path, charsmax(path))
  5733. format(path, charsmax(path), "%s/%s", path, ZP_CUSTOMIZATION_FILE)
  5734.  
  5735. // File not present
  5736. if (!file_exists(path))
  5737. {
  5738. new error[100]
  5739. formatex(error, charsmax(error), "Cannot load customization file %s!", path)
  5740. set_fail_state(error)
  5741. return;
  5742. }
  5743.  
  5744. // Set up some vars to hold parsing info
  5745. new linedata[1024], key[64], value[960], section, teams
  5746.  
  5747. // Open customization file for reading
  5748. new file = fopen(path, "rt")
  5749.  
  5750. while (file && !feof(file))
  5751. {
  5752. // Read one line at a time
  5753. fgets(file, linedata, charsmax(linedata))
  5754.  
  5755. // Replace newlines with a null character to prevent headaches
  5756. replace(linedata, charsmax(linedata), "^n", "")
  5757.  
  5758. // Blank line or comment
  5759. if (!linedata[0] || linedata[0] == ';') continue;
  5760.  
  5761. // New section starting
  5762. if (linedata[0] == '[')
  5763. {
  5764. section++
  5765. continue;
  5766. }
  5767.  
  5768. // Get key and value(s)
  5769. strtok(linedata, key, charsmax(key), value, charsmax(value), '=')
  5770.  
  5771. // Trim spaces
  5772. trim(key)
  5773. trim(value)
  5774.  
  5775. switch (section)
  5776. {
  5777. case SECTION_ACCESS_FLAGS:
  5778. {
  5779. if (equal(key, "ENABLE/DISABLE MOD"))
  5780. g_access_flag[ACCESS_ENABLE_MOD] = read_flags(value)
  5781. else if (equal(key, "ADMIN MENU"))
  5782. g_access_flag[ACCESS_ADMIN_MENU] = read_flags(value)
  5783. else if (equal(key, "START MODE INFECTION"))
  5784. g_access_flag[ACCESS_MODE_INFECTION] = read_flags(value)
  5785. else if (equal(key, "START MODE NEMESIS"))
  5786. g_access_flag[ACCESS_MODE_NEMESIS] = read_flags(value)
  5787. else if (equal(key, "START MODE SURVIVOR"))
  5788. g_access_flag[ACCESS_MODE_SURVIVOR] = read_flags(value)
  5789. else if (equal(key, "START MODE SWARM"))
  5790. g_access_flag[ACCESS_MODE_SWARM] = read_flags(value)
  5791. else if (equal(key, "START MODE MULTI"))
  5792. g_access_flag[ACCESS_MODE_MULTI] = read_flags(value)
  5793. else if (equal(key, "START MODE PLAGUE"))
  5794. g_access_flag[ACCESS_MODE_PLAGUE] = read_flags(value)
  5795. else if (equal(key, "MAKE ZOMBIE"))
  5796. g_access_flag[ACCESS_MAKE_ZOMBIE] = read_flags(value)
  5797. else if (equal(key, "MAKE HUMAN"))
  5798. g_access_flag[ACCESS_MAKE_HUMAN] = read_flags(value)
  5799. else if (equal(key, "MAKE NEMESIS"))
  5800. g_access_flag[ACCESS_MAKE_NEMESIS] = read_flags(value)
  5801. else if (equal(key, "MAKE SURVIVOR"))
  5802. g_access_flag[ACCESS_MAKE_SURVIVOR] = read_flags(value)
  5803. else if (equal(key, "RESPAWN PLAYERS"))
  5804. g_access_flag[ACCESS_RESPAWN_PLAYERS] = read_flags(value)
  5805. else if (equal(key, "ADMIN MODELS"))
  5806. g_access_flag[ACCESS_ADMIN_MODELS] = read_flags(value)
  5807. }
  5808. case SECTION_PLAYER_MODELS:
  5809. {
  5810. if (equal(key, "HUMAN"))
  5811. {
  5812. // Parse models
  5813. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  5814. {
  5815. // Trim spaces
  5816. trim(key)
  5817. trim(value)
  5818.  
  5819. // Add to models array
  5820. ArrayPushString(model_human, key)
  5821. }
  5822. }
  5823. else if (equal(key, "NEMESIS"))
  5824. {
  5825. // Parse models
  5826. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  5827. {
  5828. // Trim spaces
  5829. trim(key)
  5830. trim(value)
  5831.  
  5832. // Add to models array
  5833. ArrayPushString(model_nemesis, key)
  5834. }
  5835. }
  5836. else if (equal(key, "SURVIVOR"))
  5837. {
  5838. // Parse models
  5839. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  5840. {
  5841. // Trim spaces
  5842. trim(key)
  5843. trim(value)
  5844.  
  5845. // Add to models array
  5846. ArrayPushString(model_survivor, key)
  5847. }
  5848. }
  5849. else if (equal(key, "ADMIN ZOMBIE"))
  5850. {
  5851. // Parse models
  5852. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  5853. {
  5854. // Trim spaces
  5855. trim(key)
  5856. trim(value)
  5857.  
  5858. // Add to models array
  5859. ArrayPushString(model_admin_zombie, key)
  5860. }
  5861. }
  5862. else if (equal(key, "ADMIN HUMAN"))
  5863. {
  5864. // Parse models
  5865. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  5866. {
  5867. // Trim spaces
  5868. trim(key)
  5869. trim(value)
  5870.  
  5871. // Add to models array
  5872. ArrayPushString(model_admin_human, key)
  5873. }
  5874. }
  5875. else if (equal(key, "FORCE CONSISTENCY"))
  5876. g_force_consistency = str_to_num(value)
  5877. else if (equal(key, "SAME MODELS FOR ALL"))
  5878. g_same_models_for_all = str_to_num(value)
  5879. else if (g_same_models_for_all && equal(key, "ZOMBIE"))
  5880. {
  5881. // Parse models
  5882. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  5883. {
  5884. // Trim spaces
  5885. trim(key)
  5886. trim(value)
  5887.  
  5888. // Add to models array
  5889. ArrayPushString(g_zclass_playermodel, key)
  5890.  
  5891. // Precache model and retrieve its modelindex
  5892. formatex(linedata, charsmax(linedata), "models/player/%s/%s.mdl", key, key)
  5893. ArrayPushCell(g_zclass_modelindex, engfunc(EngFunc_PrecacheModel, linedata))
  5894. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, linedata)
  5895. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, linedata)
  5896. }
  5897. }
  5898. }
  5899. case SECTION_WEAPON_MODELS:
  5900. {
  5901. if (equal(key, "V_KNIFE HUMAN"))
  5902. copy(model_vknife_human, charsmax(model_vknife_human), value)
  5903. else if (equal(key, "V_KNIFE NEMESIS"))
  5904. copy(model_vknife_nemesis, charsmax(model_vknife_nemesis), value)
  5905. else if (equal(key, "V_M249 SURVIVOR"))
  5906. copy(model_vm249_survivor, charsmax(model_vm249_survivor), value)
  5907. else if (equal(key, "GRENADE INFECT"))
  5908. copy(model_grenade_infect, charsmax(model_grenade_infect), value)
  5909. else if (equal(key, "GRENADE FIRE"))
  5910. copy(model_grenade_fire, charsmax(model_grenade_fire), value)
  5911. else if (equal(key, "GRENADE FROST"))
  5912. copy(model_grenade_frost, charsmax(model_grenade_frost), value)
  5913. else if (equal(key, "GRENADE FLARE"))
  5914. copy(model_grenade_flare, charsmax(model_grenade_flare), value)
  5915. else if (equal(key, "V_KNIFE ADMIN HUMAN"))
  5916. copy(model_vknife_admin_human, charsmax(model_vknife_admin_human), value)
  5917. else if (equal(key, "V_KNIFE ADMIN ZOMBIE"))
  5918. copy(model_vknife_admin_zombie, charsmax(model_vknife_admin_zombie), value)
  5919. }
  5920. case SECTION_GRENADE_SPRITES:
  5921. {
  5922. if (equal(key, "TRAIL"))
  5923. copy(sprite_grenade_trail, charsmax(sprite_grenade_trail), value)
  5924. else if (equal(key, "RING"))
  5925. copy(sprite_grenade_ring, charsmax(sprite_grenade_ring), value)
  5926. else if (equal(key, "FIRE"))
  5927. copy(sprite_grenade_fire, charsmax(sprite_grenade_fire), value)
  5928. else if (equal(key, "SMOKE"))
  5929. copy(sprite_grenade_smoke, charsmax(sprite_grenade_smoke), value)
  5930. else if (equal(key, "GLASS"))
  5931. copy(sprite_grenade_glass, charsmax(sprite_grenade_glass), value)
  5932. }
  5933. case SECTION_SOUNDS:
  5934. {
  5935. if (equal(key, "WIN ZOMBIES"))
  5936. {
  5937. // Parse sounds
  5938. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  5939. {
  5940. // Trim spaces
  5941. trim(key)
  5942. trim(value)
  5943.  
  5944. // Add to sounds array
  5945. ArrayPushString(sound_win_zombies, key)
  5946. }
  5947. }
  5948. else if (equal(key, "WIN HUMANS"))
  5949. {
  5950. // Parse sounds
  5951. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  5952. {
  5953. // Trim spaces
  5954. trim(key)
  5955. trim(value)
  5956.  
  5957. // Add to sounds array
  5958. ArrayPushString(sound_win_humans, key)
  5959. }
  5960. }
  5961. else if (equal(key, "WIN NO ONE"))
  5962. {
  5963. // Parse sounds
  5964. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  5965. {
  5966. // Trim spaces
  5967. trim(key)
  5968. trim(value)
  5969.  
  5970. // Add to sounds array
  5971. ArrayPushString(sound_win_no_one, key)
  5972. }
  5973. }
  5974. else if (equal(key, "ZOMBIE INFECT"))
  5975. {
  5976. // Parse sounds
  5977. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  5978. {
  5979. // Trim spaces
  5980. trim(key)
  5981. trim(value)
  5982.  
  5983. // Add to sounds array
  5984. ArrayPushString(zombie_infect, key)
  5985. }
  5986. }
  5987. else if (equal(key, "ZOMBIE PAIN"))
  5988. {
  5989. // Parse sounds
  5990. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  5991. {
  5992. // Trim spaces
  5993. trim(key)
  5994. trim(value)
  5995.  
  5996. // Add to sounds array
  5997. ArrayPushString(zombie_pain, key)
  5998. }
  5999. }
  6000. else if (equal(key, "NEMESIS PAIN"))
  6001. {
  6002. // Parse sounds
  6003. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6004. {
  6005. // Trim spaces
  6006. trim(key)
  6007. trim(value)
  6008.  
  6009. // Add to sounds array
  6010. ArrayPushString(nemesis_pain, key)
  6011. }
  6012. }
  6013. else if (equal(key, "ZOMBIE DIE"))
  6014. {
  6015. // Parse sounds
  6016. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6017. {
  6018. // Trim spaces
  6019. trim(key)
  6020. trim(value)
  6021.  
  6022. // Add to sounds array
  6023. ArrayPushString(zombie_die, key)
  6024. }
  6025. }
  6026. else if (equal(key, "ZOMBIE FALL"))
  6027. {
  6028. // Parse sounds
  6029. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6030. {
  6031. // Trim spaces
  6032. trim(key)
  6033. trim(value)
  6034.  
  6035. // Add to sounds array
  6036. ArrayPushString(zombie_fall, key)
  6037. }
  6038. }
  6039. else if (equal(key, "ZOMBIE MISS SLASH"))
  6040. {
  6041. // Parse sounds
  6042. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6043. {
  6044. // Trim spaces
  6045. trim(key)
  6046. trim(value)
  6047.  
  6048. // Add to sounds array
  6049. ArrayPushString(zombie_miss_slash, key)
  6050. }
  6051. }
  6052. else if (equal(key, "ZOMBIE MISS WALL"))
  6053. {
  6054. // Parse sounds
  6055. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6056. {
  6057. // Trim spaces
  6058. trim(key)
  6059. trim(value)
  6060.  
  6061. // Add to sounds array
  6062. ArrayPushString(zombie_miss_wall, key)
  6063. }
  6064. }
  6065. else if (equal(key, "ZOMBIE HIT NORMAL"))
  6066. {
  6067. // Parse sounds
  6068. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6069. {
  6070. // Trim spaces
  6071. trim(key)
  6072. trim(value)
  6073.  
  6074. // Add to sounds array
  6075. ArrayPushString(zombie_hit_normal, key)
  6076. }
  6077. }
  6078. else if (equal(key, "ZOMBIE HIT STAB"))
  6079. {
  6080. // Parse sounds
  6081. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6082. {
  6083. // Trim spaces
  6084. trim(key)
  6085. trim(value)
  6086.  
  6087. // Add to sounds array
  6088. ArrayPushString(zombie_hit_stab, key)
  6089. }
  6090. }
  6091. else if (equal(key, "ZOMBIE IDLE"))
  6092. {
  6093. // Parse sounds
  6094. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6095. {
  6096. // Trim spaces
  6097. trim(key)
  6098. trim(value)
  6099.  
  6100. // Add to sounds array
  6101. ArrayPushString(zombie_idle, key)
  6102. }
  6103. }
  6104. else if (equal(key, "ZOMBIE IDLE LAST"))
  6105. {
  6106. // Parse sounds
  6107. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6108. {
  6109. // Trim spaces
  6110. trim(key)
  6111. trim(value)
  6112.  
  6113. // Add to sounds array
  6114. ArrayPushString(zombie_idle_last, key)
  6115. }
  6116. }
  6117. else if (equal(key, "ZOMBIE MADNESS"))
  6118. {
  6119. // Parse sounds
  6120. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6121. {
  6122. // Trim spaces
  6123. trim(key)
  6124. trim(value)
  6125.  
  6126. // Add to sounds array
  6127. ArrayPushString(zombie_madness, key)
  6128. }
  6129. }
  6130. else if (equal(key, "ROUND NEMESIS"))
  6131. {
  6132. // Parse sounds
  6133. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6134. {
  6135. // Trim spaces
  6136. trim(key)
  6137. trim(value)
  6138.  
  6139. // Add to sounds array
  6140. ArrayPushString(sound_nemesis, key)
  6141. }
  6142. }
  6143. else if (equal(key, "ROUND SURVIVOR"))
  6144. {
  6145. // Parse sounds
  6146. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6147. {
  6148. // Trim spaces
  6149. trim(key)
  6150. trim(value)
  6151.  
  6152. // Add to sounds array
  6153. ArrayPushString(sound_survivor, key)
  6154. }
  6155. }
  6156. else if (equal(key, "ROUND SWARM"))
  6157. {
  6158. // Parse sounds
  6159. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6160. {
  6161. // Trim spaces
  6162. trim(key)
  6163. trim(value)
  6164.  
  6165. // Add to sounds array
  6166. ArrayPushString(sound_swarm, key)
  6167. }
  6168. }
  6169. else if (equal(key, "ROUND MULTI"))
  6170. {
  6171. // Parse sounds
  6172. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6173. {
  6174. // Trim spaces
  6175. trim(key)
  6176. trim(value)
  6177.  
  6178. // Add to sounds array
  6179. ArrayPushString(sound_multi, key)
  6180. }
  6181. }
  6182. else if (equal(key, "ROUND PLAGUE"))
  6183. {
  6184. // Parse sounds
  6185. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6186. {
  6187. // Trim spaces
  6188. trim(key)
  6189. trim(value)
  6190.  
  6191. // Add to sounds array
  6192. ArrayPushString(sound_plague, key)
  6193. }
  6194. }
  6195. else if (equal(key, "GRENADE INFECT EXPLODE"))
  6196. {
  6197. // Parse sounds
  6198. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6199. {
  6200. // Trim spaces
  6201. trim(key)
  6202. trim(value)
  6203.  
  6204. // Add to sounds array
  6205. ArrayPushString(grenade_infect, key)
  6206. }
  6207. }
  6208. else if (equal(key, "GRENADE INFECT PLAYER"))
  6209. {
  6210. // Parse sounds
  6211. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6212. {
  6213. // Trim spaces
  6214. trim(key)
  6215. trim(value)
  6216.  
  6217. // Add to sounds array
  6218. ArrayPushString(grenade_infect_player, key)
  6219. }
  6220. }
  6221. else if (equal(key, "GRENADE FIRE EXPLODE"))
  6222. {
  6223. // Parse sounds
  6224. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6225. {
  6226. // Trim spaces
  6227. trim(key)
  6228. trim(value)
  6229.  
  6230. // Add to sounds array
  6231. ArrayPushString(grenade_fire, key)
  6232. }
  6233. }
  6234. else if (equal(key, "GRENADE FIRE PLAYER"))
  6235. {
  6236. // Parse sounds
  6237. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6238. {
  6239. // Trim spaces
  6240. trim(key)
  6241. trim(value)
  6242.  
  6243. // Add to sounds array
  6244. ArrayPushString(grenade_fire_player, key)
  6245. }
  6246. }
  6247. else if (equal(key, "GRENADE FROST EXPLODE"))
  6248. {
  6249. // Parse sounds
  6250. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6251. {
  6252. // Trim spaces
  6253. trim(key)
  6254. trim(value)
  6255.  
  6256. // Add to sounds array
  6257. ArrayPushString(grenade_frost, key)
  6258. }
  6259. }
  6260. else if (equal(key, "GRENADE FROST PLAYER"))
  6261. {
  6262. // Parse sounds
  6263. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6264. {
  6265. // Trim spaces
  6266. trim(key)
  6267. trim(value)
  6268.  
  6269. // Add to sounds array
  6270. ArrayPushString(grenade_frost_player, key)
  6271. }
  6272. }
  6273. else if (equal(key, "GRENADE FROST BREAK"))
  6274. {
  6275. // Parse sounds
  6276. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6277. {
  6278. // Trim spaces
  6279. trim(key)
  6280. trim(value)
  6281.  
  6282. // Add to sounds array
  6283. ArrayPushString(grenade_frost_break, key)
  6284. }
  6285. }
  6286. else if (equal(key, "GRENADE FLARE"))
  6287. {
  6288. // Parse sounds
  6289. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6290. {
  6291. // Trim spaces
  6292. trim(key)
  6293. trim(value)
  6294.  
  6295. // Add to sounds array
  6296. ArrayPushString(grenade_flare, key)
  6297. }
  6298. }
  6299. else if (equal(key, "ANTIDOTE"))
  6300. {
  6301. // Parse sounds
  6302. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6303. {
  6304. // Trim spaces
  6305. trim(key)
  6306. trim(value)
  6307.  
  6308. // Add to sounds array
  6309. ArrayPushString(sound_antidote, key)
  6310. }
  6311. }
  6312. else if (equal(key, "THUNDER"))
  6313. {
  6314. // Parse sounds
  6315. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6316. {
  6317. // Trim spaces
  6318. trim(key)
  6319. trim(value)
  6320.  
  6321. // Add to sounds array
  6322. ArrayPushString(sound_thunder, key)
  6323. }
  6324. }
  6325. }
  6326. case SECTION_AMBIENCE_SOUNDS:
  6327. {
  6328. if (equal(key, "INFECTION ENABLE"))
  6329. g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] = str_to_num(value)
  6330. else if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] && equal(key, "INFECTION SOUNDS"))
  6331. {
  6332. // Parse sounds
  6333. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6334. {
  6335. // Trim spaces
  6336. trim(key)
  6337. trim(value)
  6338.  
  6339. // Add to sounds array
  6340. ArrayPushString(sound_ambience1, key)
  6341. ArrayPushCell(sound_ambience1_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
  6342. }
  6343. }
  6344. else if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] && equal(key, "INFECTION DURATIONS"))
  6345. {
  6346. // Parse sounds
  6347. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6348. {
  6349. // Trim spaces
  6350. trim(key)
  6351. trim(value)
  6352.  
  6353. // Add to sounds array
  6354. ArrayPushCell(sound_ambience1_duration, str_to_num(key))
  6355. }
  6356. }
  6357. else if (equal(key, "NEMESIS ENABLE"))
  6358. g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] = str_to_num(value)
  6359. else if (g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] && equal(key, "NEMESIS SOUNDS"))
  6360. {
  6361. // Parse sounds
  6362. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6363. {
  6364. // Trim spaces
  6365. trim(key)
  6366. trim(value)
  6367.  
  6368. // Add to sounds array
  6369. ArrayPushString(sound_ambience2, key)
  6370. ArrayPushCell(sound_ambience2_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
  6371. }
  6372. }
  6373. else if (g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] && equal(key, "NEMESIS DURATIONS"))
  6374. {
  6375. // Parse sounds
  6376. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6377. {
  6378. // Trim spaces
  6379. trim(key)
  6380. trim(value)
  6381.  
  6382. // Add to sounds array
  6383. ArrayPushCell(sound_ambience2_duration, str_to_num(key))
  6384. }
  6385. }
  6386. else if (equal(key, "SURVIVOR ENABLE"))
  6387. g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] = str_to_num(value)
  6388. else if (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] && equal(key, "SURVIVOR SOUNDS"))
  6389. {
  6390. // Parse sounds
  6391. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6392. {
  6393. // Trim spaces
  6394. trim(key)
  6395. trim(value)
  6396.  
  6397. // Add to sounds array
  6398. ArrayPushString(sound_ambience3, key)
  6399. ArrayPushCell(sound_ambience3_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
  6400. }
  6401. }
  6402. else if (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] && equal(key, "SURVIVOR DURATIONS"))
  6403. {
  6404. // Parse sounds
  6405. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6406. {
  6407. // Trim spaces
  6408. trim(key)
  6409. trim(value)
  6410.  
  6411. // Add to sounds array
  6412. ArrayPushCell(sound_ambience3_duration, str_to_num(key))
  6413. }
  6414. }
  6415. else if (equal(key, "SWARM ENABLE"))
  6416. g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] = str_to_num(value)
  6417. else if (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] && equal(key, "SWARM SOUNDS"))
  6418. {
  6419. // Parse sounds
  6420. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6421. {
  6422. // Trim spaces
  6423. trim(key)
  6424. trim(value)
  6425.  
  6426. // Add to sounds array
  6427. ArrayPushString(sound_ambience4, key)
  6428. ArrayPushCell(sound_ambience4_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
  6429. }
  6430. }
  6431. else if (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] && equal(key, "SWARM DURATIONS"))
  6432. {
  6433. // Parse sounds
  6434. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6435. {
  6436. // Trim spaces
  6437. trim(key)
  6438. trim(value)
  6439.  
  6440. // Add to sounds array
  6441. ArrayPushCell(sound_ambience4_duration, str_to_num(key))
  6442. }
  6443. }
  6444. else if (equal(key, "PLAGUE ENABLE"))
  6445. g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] = str_to_num(value)
  6446. else if (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] && equal(key, "PLAGUE SOUNDS"))
  6447. {
  6448. // Parse sounds
  6449. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6450. {
  6451. // Trim spaces
  6452. trim(key)
  6453. trim(value)
  6454.  
  6455. // Add to sounds array
  6456. ArrayPushString(sound_ambience5, key)
  6457. ArrayPushCell(sound_ambience5_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
  6458. }
  6459. }
  6460. else if (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] && equal(key, "PLAGUE DURATIONS"))
  6461. {
  6462. // Parse sounds
  6463. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6464. {
  6465. // Trim spaces
  6466. trim(key)
  6467. trim(value)
  6468.  
  6469. // Add to sounds array
  6470. ArrayPushCell(sound_ambience5_duration, str_to_num(key))
  6471. }
  6472. }
  6473. }
  6474. case SECTION_BUY_MENU_WEAPONS:
  6475. {
  6476. if (equal(key, "PRIMARY"))
  6477. {
  6478. // Parse weapons
  6479. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6480. {
  6481. // Trim spaces
  6482. trim(key)
  6483. trim(value)
  6484.  
  6485. // Add to weapons array
  6486. ArrayPushString(g_primary_items, key)
  6487. ArrayPushCell(g_primary_weaponids, cs_weapon_name_to_id(key))
  6488. }
  6489. }
  6490. else if (equal(key, "SECONDARY"))
  6491. {
  6492. // Parse weapons
  6493. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6494. {
  6495. // Trim spaces
  6496. trim(key)
  6497. trim(value)
  6498.  
  6499. // Add to weapons array
  6500. ArrayPushString(g_secondary_items, key)
  6501. ArrayPushCell(g_secondary_weaponids, cs_weapon_name_to_id(key))
  6502. }
  6503. }
  6504. else if (equal(key, "ADDITIONAL ITEMS"))
  6505. {
  6506. // Parse weapons
  6507. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6508. {
  6509. // Trim spaces
  6510. trim(key)
  6511. trim(value)
  6512.  
  6513. // Add to weapons array
  6514. ArrayPushString(g_additional_items, key)
  6515. }
  6516. }
  6517. }
  6518. case SECTION_EXTRA_ITEMS_WEAPONS:
  6519. {
  6520. if (equal(key, "NAMES"))
  6521. {
  6522. // Parse weapon items
  6523. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6524. {
  6525. // Trim spaces
  6526. trim(key)
  6527. trim(value)
  6528.  
  6529. // Add to weapons array
  6530. ArrayPushString(g_extraweapon_names, key)
  6531. }
  6532. }
  6533. else if (equal(key, "ITEMS"))
  6534. {
  6535. // Parse weapon items
  6536. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6537. {
  6538. // Trim spaces
  6539. trim(key)
  6540. trim(value)
  6541.  
  6542. // Add to weapons array
  6543. ArrayPushString(g_extraweapon_items, key)
  6544. }
  6545. }
  6546. else if (equal(key, "COSTS"))
  6547. {
  6548. // Parse weapon items
  6549. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6550. {
  6551. // Trim spaces
  6552. trim(key)
  6553. trim(value)
  6554.  
  6555. // Add to weapons array
  6556. ArrayPushCell(g_extraweapon_costs, str_to_num(key))
  6557. }
  6558. }
  6559. }
  6560. case SECTION_HARD_CODED_ITEMS_COSTS:
  6561. {
  6562. if (equal(key, "NIGHT VISION"))
  6563. g_extra_costs2[EXTRA_NVISION] = str_to_num(value)
  6564. else if (equal(key, "ANTIDOTE"))
  6565. g_extra_costs2[EXTRA_ANTIDOTE] = str_to_num(value)
  6566. else if (equal(key, "ZOMBIE MADNESS"))
  6567. g_extra_costs2[EXTRA_MADNESS] = str_to_num(value)
  6568. else if (equal(key, "INFECTION BOMB"))
  6569. g_extra_costs2[EXTRA_INFBOMB] = str_to_num(value)
  6570. }
  6571. case SECTION_WEATHER_EFFECTS:
  6572. {
  6573. if (equal(key, "RAIN"))
  6574. g_ambience_rain = str_to_num(value)
  6575. else if (equal(key, "SNOW"))
  6576. g_ambience_snow = str_to_num(value)
  6577. else if (equal(key, "FOG"))
  6578. g_ambience_fog = str_to_num(value)
  6579. else if (equal(key, "FOG DENSITY"))
  6580. copy(g_fog_density, charsmax(g_fog_density), value)
  6581. else if (equal(key, "FOG COLOR"))
  6582. copy(g_fog_color, charsmax(g_fog_color), value)
  6583. }
  6584. case SECTION_SKY:
  6585. {
  6586. if (equal(key, "ENABLE"))
  6587. g_sky_enable = str_to_num(value)
  6588. else if (equal(key, "SKY NAMES"))
  6589. {
  6590. // Parse sky names
  6591. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6592. {
  6593. // Trim spaces
  6594. trim(key)
  6595. trim(value)
  6596.  
  6597. // Add to skies array
  6598. ArrayPushString(g_sky_names, key)
  6599.  
  6600. // Preache custom sky files
  6601. formatex(linedata, charsmax(linedata), "gfx/env/%sbk.tga", key)
  6602. engfunc(EngFunc_PrecacheGeneric, linedata)
  6603. formatex(linedata, charsmax(linedata), "gfx/env/%sdn.tga", key)
  6604. engfunc(EngFunc_PrecacheGeneric, linedata)
  6605. formatex(linedata, charsmax(linedata), "gfx/env/%sft.tga", key)
  6606. engfunc(EngFunc_PrecacheGeneric, linedata)
  6607. formatex(linedata, charsmax(linedata), "gfx/env/%slf.tga", key)
  6608. engfunc(EngFunc_PrecacheGeneric, linedata)
  6609. formatex(linedata, charsmax(linedata), "gfx/env/%srt.tga", key)
  6610. engfunc(EngFunc_PrecacheGeneric, linedata)
  6611. formatex(linedata, charsmax(linedata), "gfx/env/%sup.tga", key)
  6612. engfunc(EngFunc_PrecacheGeneric, linedata)
  6613. }
  6614. }
  6615. }
  6616. case SECTION_LIGHTNING:
  6617. {
  6618. if (equal(key, "LIGHTS"))
  6619. {
  6620. // Parse lights
  6621. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6622. {
  6623. // Trim spaces
  6624. trim(key)
  6625. trim(value)
  6626.  
  6627. // Add to lightning array
  6628. ArrayPushString(lights_thunder, key)
  6629. }
  6630. }
  6631. }
  6632. case SECTION_ZOMBIE_DECALS:
  6633. {
  6634. if (equal(key, "DECALS"))
  6635. {
  6636. // Parse decals
  6637. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6638. {
  6639. // Trim spaces
  6640. trim(key)
  6641. trim(value)
  6642.  
  6643. // Add to zombie decals array
  6644. ArrayPushCell(zombie_decals, str_to_num(key))
  6645. }
  6646. }
  6647. }
  6648. case SECTION_KNOCKBACK:
  6649. {
  6650. // Format weapon entity name
  6651. strtolower(key)
  6652. format(key, charsmax(key), "weapon_%s", key)
  6653.  
  6654. // Add value to knockback power array
  6655. kb_weapon_power[cs_weapon_name_to_id(key)] = str_to_float(value)
  6656. }
  6657. case SECTION_OBJECTIVE_ENTS:
  6658. {
  6659. if (equal(key, "CLASSNAMES"))
  6660. {
  6661. // Parse classnames
  6662. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6663. {
  6664. // Trim spaces
  6665. trim(key)
  6666. trim(value)
  6667.  
  6668. // Add to objective ents array
  6669. ArrayPushString(g_objective_ents, key)
  6670. }
  6671. }
  6672. }
  6673. case SECTION_SVC_BAD:
  6674. {
  6675. if (equal(key, "MODELCHANGE DELAY"))
  6676. g_modelchange_delay = str_to_float(value)
  6677. else if (equal(key, "HANDLE MODELS ON SEPARATE ENT"))
  6678. g_handle_models_on_separate_ent = str_to_num(value)
  6679. else if (equal(key, "SET MODELINDEX OFFSET"))
  6680. g_set_modelindex_offset = str_to_num(value)
  6681. }
  6682. }
  6683. }
  6684. if (file) fclose(file)
  6685.  
  6686. // Build zombie classes file path
  6687. get_configsdir(path, charsmax(path))
  6688. format(path, charsmax(path), "%s/%s", path, ZP_ZOMBIECLASSES_FILE)
  6689.  
  6690. // Parse if present
  6691. if (file_exists(path))
  6692. {
  6693. // Open zombie classes file for reading
  6694. file = fopen(path, "rt")
  6695.  
  6696. while (file && !feof(file))
  6697. {
  6698. // Read one line at a time
  6699. fgets(file, linedata, charsmax(linedata))
  6700.  
  6701. // Replace newlines with a null character to prevent headaches
  6702. replace(linedata, charsmax(linedata), "^n", "")
  6703.  
  6704. // Blank line or comment
  6705. if (!linedata[0] || linedata[0] == ';') continue;
  6706.  
  6707. // New class starting
  6708. if (linedata[0] == '[')
  6709. {
  6710. // Remove first and last characters (braces)
  6711. linedata[strlen(linedata) - 1] = 0
  6712. copy(linedata, charsmax(linedata), linedata[1])
  6713.  
  6714. // Store its real name for future reference
  6715. ArrayPushString(g_zclass2_realname, linedata)
  6716. continue;
  6717. }
  6718.  
  6719. // Get key and value(s)
  6720. strtok(linedata, key, charsmax(key), value, charsmax(value), '=')
  6721.  
  6722. // Trim spaces
  6723. trim(key)
  6724. trim(value)
  6725.  
  6726. if (equal(key, "NAME"))
  6727. ArrayPushString(g_zclass2_name, value)
  6728. else if (equal(key, "INFO"))
  6729. ArrayPushString(g_zclass2_info, value)
  6730. else if (equal(key, "MODELS"))
  6731. {
  6732. // Set models start index
  6733. ArrayPushCell(g_zclass2_modelsstart, ArraySize(g_zclass2_playermodel))
  6734.  
  6735. // Parse class models
  6736. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6737. {
  6738. // Trim spaces
  6739. trim(key)
  6740. trim(value)
  6741.  
  6742. // Add to class models array
  6743. ArrayPushString(g_zclass2_playermodel, key)
  6744. ArrayPushCell(g_zclass2_modelindex, -1)
  6745. }
  6746.  
  6747. // Set models end index
  6748. ArrayPushCell(g_zclass2_modelsend, ArraySize(g_zclass2_playermodel))
  6749. }
  6750. else if (equal(key, "CLAWMODEL"))
  6751. ArrayPushString(g_zclass2_clawmodel, value)
  6752. else if (equal(key, "HEALTH"))
  6753. ArrayPushCell(g_zclass2_hp, str_to_num(value))
  6754. else if (equal(key, "SPEED"))
  6755. ArrayPushCell(g_zclass2_spd, str_to_num(value))
  6756. else if (equal(key, "GRAVITY"))
  6757. ArrayPushCell(g_zclass2_grav, str_to_float(value))
  6758. else if (equal(key, "KNOCKBACK"))
  6759. ArrayPushCell(g_zclass2_kb, str_to_float(value))
  6760. }
  6761. if (file) fclose(file)
  6762. }
  6763.  
  6764. // Build extra items file path
  6765. get_configsdir(path, charsmax(path))
  6766. format(path, charsmax(path), "%s/%s", path, ZP_EXTRAITEMS_FILE)
  6767.  
  6768. // Parse if present
  6769. if (file_exists(path))
  6770. {
  6771. // Open extra items file for reading
  6772. file = fopen(path, "rt")
  6773.  
  6774. while (file && !feof(file))
  6775. {
  6776. // Read one line at a time
  6777. fgets(file, linedata, charsmax(linedata))
  6778.  
  6779. // Replace newlines with a null character to prevent headaches
  6780. replace(linedata, charsmax(linedata), "^n", "")
  6781.  
  6782. // Blank line or comment
  6783. if (!linedata[0] || linedata[0] == ';') continue;
  6784.  
  6785. // New item starting
  6786. if (linedata[0] == '[')
  6787. {
  6788. // Remove first and last characters (braces)
  6789. linedata[strlen(linedata) - 1] = 0
  6790. copy(linedata, charsmax(linedata), linedata[1])
  6791.  
  6792. // Store its real name for future reference
  6793. ArrayPushString(g_extraitem2_realname, linedata)
  6794. continue;
  6795. }
  6796.  
  6797. // Get key and value(s)
  6798. strtok(linedata, key, charsmax(key), value, charsmax(value), '=')
  6799.  
  6800. // Trim spaces
  6801. trim(key)
  6802. trim(value)
  6803.  
  6804. if (equal(key, "NAME"))
  6805. ArrayPushString(g_extraitem2_name, value)
  6806. else if (equal(key, "COST"))
  6807. ArrayPushCell(g_extraitem2_cost, str_to_num(value))
  6808. else if (equal(key, "TEAMS"))
  6809. {
  6810. // Clear teams bitsum
  6811. teams = 0
  6812.  
  6813. // Parse teams
  6814. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6815. {
  6816. // Trim spaces
  6817. trim(key)
  6818. trim(value)
  6819.  
  6820. if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_ZOMBIE]))
  6821. teams |= ZP_TEAM_ZOMBIE
  6822. else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_HUMAN]))
  6823. teams |= ZP_TEAM_HUMAN
  6824. else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_NEMESIS]))
  6825. teams |= ZP_TEAM_NEMESIS
  6826. else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_SURVIVOR]))
  6827. teams |= ZP_TEAM_SURVIVOR
  6828. }
  6829.  
  6830. // Add to teams array
  6831. ArrayPushCell(g_extraitem2_team, teams)
  6832. }
  6833. }
  6834. if (file) fclose(file)
  6835. }
  6836. }
  6837.  
  6838. save_customization()
  6839. {
  6840. new i, k, buffer[512]
  6841.  
  6842. // Build zombie classes file path
  6843. new path[64]
  6844. get_configsdir(path, charsmax(path))
  6845. format(path, charsmax(path), "%s/%s", path, ZP_ZOMBIECLASSES_FILE)
  6846.  
  6847. // Open zombie classes file for appending data
  6848. new file = fopen(path, "at"), size = ArraySize(g_zclass_name)
  6849.  
  6850. // Add any new zombie classes data at the end if needed
  6851. for (i = 0; i < size; i++)
  6852. {
  6853. if (ArrayGetCell(g_zclass_new, i))
  6854. {
  6855. // Add real name
  6856. ArrayGetString(g_zclass_name, i, buffer, charsmax(buffer))
  6857. format(buffer, charsmax(buffer), "^n[%s]", buffer)
  6858. fputs(file, buffer)
  6859.  
  6860. // Add caption
  6861. ArrayGetString(g_zclass_name, i, buffer, charsmax(buffer))
  6862. format(buffer, charsmax(buffer), "^nNAME = %s", buffer)
  6863. fputs(file, buffer)
  6864.  
  6865. // Add info
  6866. ArrayGetString(g_zclass_info, i, buffer, charsmax(buffer))
  6867. format(buffer, charsmax(buffer), "^nINFO = %s", buffer)
  6868. fputs(file, buffer)
  6869.  
  6870. // Add models
  6871. for (k = ArrayGetCell(g_zclass_modelsstart, i); k < ArrayGetCell(g_zclass_modelsend, i); k++)
  6872. {
  6873. if (k == ArrayGetCell(g_zclass_modelsstart, i))
  6874. {
  6875. // First model, overwrite buffer
  6876. ArrayGetString(g_zclass_playermodel, k, buffer, charsmax(buffer))
  6877. }
  6878. else
  6879. {
  6880. // Successive models, append to buffer
  6881. ArrayGetString(g_zclass_playermodel, k, path, charsmax(path))
  6882. format(buffer, charsmax(buffer), "%s , %s", buffer, path)
  6883. }
  6884. }
  6885. format(buffer, charsmax(buffer), "^nMODELS = %s", buffer)
  6886. fputs(file, buffer)
  6887.  
  6888. // Add clawmodel
  6889. ArrayGetString(g_zclass_clawmodel, i, buffer, charsmax(buffer))
  6890. format(buffer, charsmax(buffer), "^nCLAWMODEL = %s", buffer)
  6891. fputs(file, buffer)
  6892.  
  6893. // Add health
  6894. formatex(buffer, charsmax(buffer), "^nHEALTH = %d", ArrayGetCell(g_zclass_hp, i))
  6895. fputs(file, buffer)
  6896.  
  6897. // Add speed
  6898. formatex(buffer, charsmax(buffer), "^nSPEED = %d", ArrayGetCell(g_zclass_spd, i))
  6899. fputs(file, buffer)
  6900.  
  6901. // Add gravity
  6902. formatex(buffer, charsmax(buffer), "^nGRAVITY = %.2f", Float:ArrayGetCell(g_zclass_grav, i))
  6903. fputs(file, buffer)
  6904.  
  6905. // Add knockback
  6906. formatex(buffer, charsmax(buffer), "^nKNOCKBACK = %.2f^n", Float:ArrayGetCell(g_zclass_kb, i))
  6907. fputs(file, buffer)
  6908. }
  6909. }
  6910. fclose(file)
  6911.  
  6912. // Build extra items file path
  6913. get_configsdir(path, charsmax(path))
  6914. format(path, charsmax(path), "%s/%s", path, ZP_EXTRAITEMS_FILE)
  6915.  
  6916. // Open extra items file for appending data
  6917. file = fopen(path, "at")
  6918. size = ArraySize(g_extraitem_name)
  6919.  
  6920. // Add any new extra items data at the end if needed
  6921. for (i = EXTRAS_CUSTOM_STARTID; i < size; i++)
  6922. {
  6923. if (ArrayGetCell(g_extraitem_new, i))
  6924. {
  6925. // Add real name
  6926. ArrayGetString(g_extraitem_name, i, buffer, charsmax(buffer))
  6927. format(buffer, charsmax(buffer), "^n[%s]", buffer)
  6928. fputs(file, buffer)
  6929.  
  6930. // Add caption
  6931. ArrayGetString(g_extraitem_name, i, buffer, charsmax(buffer))
  6932. format(buffer, charsmax(buffer), "^nNAME = %s", buffer)
  6933. fputs(file, buffer)
  6934.  
  6935. // Add cost
  6936. formatex(buffer, charsmax(buffer), "^nCOST = %d", ArrayGetCell(g_extraitem_cost, i))
  6937. fputs(file, buffer)
  6938.  
  6939. // Add team
  6940. formatex(buffer, charsmax(buffer), "^nTEAMS = %s^n", ZP_TEAM_NAMES[ArrayGetCell(g_extraitem_team, i)])
  6941. fputs(file, buffer)
  6942. }
  6943. }
  6944. fclose(file)
  6945.  
  6946. // Free arrays containing class/item overrides
  6947. ArrayDestroy(g_zclass2_realname)
  6948. ArrayDestroy(g_zclass2_name)
  6949. ArrayDestroy(g_zclass2_info)
  6950. ArrayDestroy(g_zclass2_modelsstart)
  6951. ArrayDestroy(g_zclass2_modelsend)
  6952. ArrayDestroy(g_zclass2_playermodel)
  6953. ArrayDestroy(g_zclass2_modelindex)
  6954. ArrayDestroy(g_zclass2_clawmodel)
  6955. ArrayDestroy(g_zclass2_hp)
  6956. ArrayDestroy(g_zclass2_spd)
  6957. ArrayDestroy(g_zclass2_grav)
  6958. ArrayDestroy(g_zclass2_kb)
  6959. ArrayDestroy(g_zclass_new)
  6960. ArrayDestroy(g_extraitem2_realname)
  6961. ArrayDestroy(g_extraitem2_name)
  6962. ArrayDestroy(g_extraitem2_cost)
  6963. ArrayDestroy(g_extraitem2_team)
  6964. ArrayDestroy(g_extraitem_new)
  6965. }
  6966.  
  6967. // Register Ham Forwards for CZ bots
  6968. public register_ham_czbots(id)
  6969. {
  6970. // Make sure it's a CZ bot and it's still connected
  6971. if (g_hamczbots || !g_isconnected[id] || !get_pcvar_num(cvar_botquota))
  6972. return;
  6973.  
  6974. RegisterHamFromEntity(Ham_Spawn, id, "fw_PlayerSpawn_Post", 1)
  6975. RegisterHamFromEntity(Ham_Killed, id, "fw_PlayerKilled")
  6976. RegisterHamFromEntity(Ham_Killed, id, "fw_PlayerKilled_Post", 1)
  6977. RegisterHamFromEntity(Ham_TakeDamage, id, "fw_TakeDamage")
  6978. RegisterHamFromEntity(Ham_TakeDamage, id, "fw_TakeDamage_Post", 1)
  6979. RegisterHamFromEntity(Ham_TraceAttack, id, "fw_TraceAttack")
  6980.  
  6981. // Ham forwards for CZ bots succesfully registered
  6982. g_hamczbots = true
  6983.  
  6984. // If the bot has already spawned, call the forward manually for him
  6985. if (is_user_alive(id)) fw_PlayerSpawn_Post(id)
  6986. }
  6987.  
  6988. // Disable minmodels task
  6989. public disable_minmodels(id)
  6990. {
  6991. if (!g_isconnected[id]) return;
  6992. client_cmd(id, "cl_minmodels 0")
  6993. }
  6994.  
  6995. // Bots automatically buy extra items
  6996. public bot_buy_extras(taskid)
  6997. {
  6998. // Nemesis or Survivor bots have nothing to buy by default
  6999. if (!g_isalive[ID_SPAWN] || g_survivor[ID_SPAWN] || g_nemesis[ID_SPAWN])
  7000. return;
  7001.  
  7002. if (!g_zombie[ID_SPAWN]) // human bots
  7003. {
  7004. // Attempt to buy Night Vision
  7005. buy_extra_item(ID_SPAWN, EXTRA_NVISION)
  7006.  
  7007. // Attempt to buy a weapon
  7008. buy_extra_item(ID_SPAWN, random_num(EXTRA_WEAPONS_STARTID, EXTRAS_CUSTOM_STARTID-1))
  7009. }
  7010. else // zombie bots
  7011. {
  7012. // Attempt to buy an Antidote
  7013. buy_extra_item(ID_SPAWN, EXTRA_ANTIDOTE)
  7014. }
  7015. }
  7016.  
  7017. // Refill BP Ammo Task
  7018. public refill_bpammo(const args[], id)
  7019. {
  7020. // Player died or turned into a zombie
  7021. if (!g_isalive[id] || g_zombie[id])
  7022. return;
  7023.  
  7024. set_msg_block(g_msgAmmoPickup, BLOCK_ONCE)
  7025. ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[REFILL_WEAPONID], AMMOTYPE[REFILL_WEAPONID], MAXBPAMMO[REFILL_WEAPONID])
  7026. }
  7027.  
  7028. // Balance Teams Task
  7029. balance_teams()
  7030. {
  7031. // Get amount of users playing
  7032. static iPlayersnum
  7033. iPlayersnum = fnGetPlaying()
  7034.  
  7035. // No players, don't bother
  7036. if (iPlayersnum < 1) return;
  7037.  
  7038. // Split players evenly
  7039. static iTerrors, iMaxTerrors, id, team[33]
  7040. iMaxTerrors = iPlayersnum/2
  7041. iTerrors = 0
  7042.  
  7043. // First, set everyone to CT
  7044. for (id = 1; id <= g_maxplayers; id++)
  7045. {
  7046. // Skip if not connected
  7047. if (!g_isconnected[id])
  7048. continue;
  7049.  
  7050. team[id] = fm_cs_get_user_team(id)
  7051.  
  7052. // Skip if not playing
  7053. if (team[id] == FM_CS_TEAM_SPECTATOR || team[id] == FM_CS_TEAM_UNASSIGNED)
  7054. continue;
  7055.  
  7056. // Set team
  7057. remove_task(id+TASK_TEAM)
  7058. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  7059. team[id] = FM_CS_TEAM_CT
  7060. }
  7061.  
  7062. // Then randomly set half of the players to Terrorists
  7063. while (iTerrors < iMaxTerrors)
  7064. {
  7065. // Keep looping through all players
  7066. if (++id > g_maxplayers) id = 1
  7067.  
  7068. // Skip if not connected
  7069. if (!g_isconnected[id])
  7070. continue;
  7071.  
  7072. // Skip if not playing or already a Terrorist
  7073. if (team[id] != FM_CS_TEAM_CT)
  7074. continue;
  7075.  
  7076. // Random chance
  7077. if (random_num(0, 1))
  7078. {
  7079. fm_cs_set_user_team(id, FM_CS_TEAM_T)
  7080. team[id] = FM_CS_TEAM_T
  7081. iTerrors++
  7082. }
  7083. }
  7084. }
  7085.  
  7086. // Welcome Message Task
  7087. public welcome_msg()
  7088. {
  7089. // Show mod info
  7090. zp_colored_print(0, "^x01**** ^x04Welcome to Zombie Arena^x01 ****")
  7091. zp_colored_print(0, "^x04[Zombie Arena]^x01 %L", LANG_PLAYER, "NOTICE_INFO1")
  7092. if (!get_pcvar_num(cvar_infammo)) zp_colored_print(0, "^x04[Zombie Arena]^x01 %L", LANG_PLAYER, "NOTICE_INFO2")
  7093.  
  7094. // Show T-virus HUD notice
  7095. set_hudmessage(0, 125, 200, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
  7096. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_VIRUS_FREE")
  7097. }
  7098.  
  7099. // Respawn Player Task
  7100. public respawn_player_task(taskid)
  7101. {
  7102. // Get player's team
  7103. static team
  7104. team = fm_cs_get_user_team(ID_SPAWN)
  7105.  
  7106. // Respawn player automatically if allowed on current round
  7107. if (!g_endround && team != FM_CS_TEAM_SPECTATOR && team != FM_CS_TEAM_UNASSIGNED && !g_isalive[ID_SPAWN] && (!g_survround || get_pcvar_num(cvar_allowrespawnsurv)) && (!g_swarmround || get_pcvar_num(cvar_allowrespawnswarm)) && (!g_nemround || get_pcvar_num(cvar_allowrespawnnem)) && (!g_plagueround || get_pcvar_num(cvar_allowrespawnplague)))
  7108. {
  7109. // Infection rounds = none of the above
  7110. if (!get_pcvar_num(cvar_allowrespawninfection) && !g_survround && !g_nemround && !g_swarmround && !g_plagueround)
  7111. return;
  7112.  
  7113. // Override respawn as zombie setting on nemesis and survivor rounds
  7114. if (g_survround) g_respawn_as_zombie[ID_SPAWN] = true
  7115. else if (g_nemround) g_respawn_as_zombie[ID_SPAWN] = false
  7116.  
  7117. respawn_player_manually(ID_SPAWN)
  7118. }
  7119. }
  7120.  
  7121. // Respawn Player Manually (called after respawn checks are done)
  7122. respawn_player_manually(id)
  7123. {
  7124. // Set proper team before respawning, so that the TeamInfo message that's sent doesn't confuse PODBots
  7125. if (g_respawn_as_zombie[id])
  7126. fm_cs_set_user_team(id, FM_CS_TEAM_T)
  7127. else
  7128. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  7129.  
  7130. // Respawning a player has never been so easy
  7131. ExecuteHamB(Ham_CS_RoundRespawn, id)
  7132. }
  7133.  
  7134. // Check Round Task -check that we still have both zombies and humans on a round-
  7135. check_round(leaving_player)
  7136. {
  7137. // Round ended or make_a_zombie task still active
  7138. if (g_endround || task_exists(TASK_MAKEZOMBIE))
  7139. return;
  7140.  
  7141. // Get alive players count
  7142. static iPlayersnum, id
  7143. iPlayersnum = fnGetAlive()
  7144.  
  7145. // Last alive player, don't bother
  7146. if (iPlayersnum < 2)
  7147. return;
  7148.  
  7149. // Last zombie disconnecting
  7150. if (g_zombie[leaving_player] && fnGetZombies() == 1)
  7151. {
  7152. // Only one CT left, don't bother
  7153. if (fnGetHumans() == 1 && fnGetCTs() == 1)
  7154. return;
  7155.  
  7156. // Pick a random one to take his place
  7157. while ((id = fnGetRandomAlive(random_num(1, iPlayersnum))) == leaving_player ) { /* keep looping */ }
  7158.  
  7159. // Show last zombie left notice
  7160. zp_colored_print(0, "^x04[Zombie Arena]^x01 %L", LANG_PLAYER, "LAST_ZOMBIE_LEFT", g_playername[id])
  7161.  
  7162. // Set player leaving flag
  7163. g_lastplayerleaving = true
  7164.  
  7165. // Turn into a Nemesis or just a zombie?
  7166. if (g_nemesis[leaving_player])
  7167. zombieme(id, 0, 1, 0, 0)
  7168. else
  7169. zombieme(id, 0, 0, 0, 0)
  7170.  
  7171. // Remove player leaving flag
  7172. g_lastplayerleaving = false
  7173.  
  7174. // If Nemesis, set chosen player's health to that of the one who's leaving
  7175. if (get_pcvar_num(cvar_keephealthondisconnect) && g_nemesis[leaving_player])
  7176. fm_set_user_health(id, pev(leaving_player, pev_health))
  7177. }
  7178.  
  7179. // Last human disconnecting
  7180. else if (!g_zombie[leaving_player] && fnGetHumans() == 1)
  7181. {
  7182. // Only one T left, don't bother
  7183. if (fnGetZombies() == 1 && fnGetTs() == 1)
  7184. return;
  7185.  
  7186. // Pick a random one to take his place
  7187. while ((id = fnGetRandomAlive(random_num(1, iPlayersnum))) == leaving_player ) { /* keep looping */ }
  7188.  
  7189. // Show last human left notice
  7190. zp_colored_print(0, "^x04[Zombie Arena]^x01 %L", LANG_PLAYER, "LAST_HUMAN_LEFT", g_playername[id])
  7191.  
  7192. // Set player leaving flag
  7193. g_lastplayerleaving = true
  7194.  
  7195. // Turn into a Survivor or just a human?
  7196. if (g_survivor[leaving_player])
  7197. humanme(id, 1, 0)
  7198. else
  7199. humanme(id, 0, 0)
  7200.  
  7201. // Remove player leaving flag
  7202. g_lastplayerleaving = false
  7203.  
  7204. // If Survivor, set chosen player's health to that of the one who's leaving
  7205. if (get_pcvar_num(cvar_keephealthondisconnect) && g_survivor[leaving_player])
  7206. fm_set_user_health(id, pev(leaving_player, pev_health))
  7207. }
  7208. }
  7209.  
  7210. // Lighting Effects Task
  7211. public lighting_effects()
  7212. {
  7213. // Cache some CVAR values at every 5 secs
  7214. cache_cvars()
  7215.  
  7216. // Get lighting style
  7217. static lighting[2]
  7218. get_pcvar_string(cvar_lighting, lighting, charsmax(lighting))
  7219. strtolower(lighting)
  7220.  
  7221. // Lighting disabled? ["0"]
  7222. if (lighting[0] == '0')
  7223. return;
  7224.  
  7225. // Darkest light settings?
  7226. if (lighting[0] >= 'a' && lighting[0] <= 'd')
  7227. {
  7228. static thunderclap_in_progress, Float:thunder
  7229. thunderclap_in_progress = task_exists(TASK_THUNDER)
  7230. thunder = get_pcvar_float(cvar_thunder)
  7231.  
  7232. // Set thunderclap tasks if not existant
  7233. if (thunder > 0.0 && !task_exists(TASK_THUNDER_PRE) && !thunderclap_in_progress)
  7234. {
  7235. g_lights_i = 0
  7236. ArrayGetString(lights_thunder, random_num(0, ArraySize(lights_thunder) - 1), g_lights_cycle, charsmax(g_lights_cycle))
  7237. g_lights_cycle_len = strlen(g_lights_cycle)
  7238. set_task(thunder, "thunderclap", TASK_THUNDER_PRE)
  7239. }
  7240.  
  7241. // Set lighting only when no thunderclaps are going on
  7242. if (!thunderclap_in_progress) engfunc(EngFunc_LightStyle, 0, lighting)
  7243. }
  7244. else
  7245. {
  7246. // Remove thunderclap tasks
  7247. remove_task(TASK_THUNDER_PRE)
  7248. remove_task(TASK_THUNDER)
  7249.  
  7250. // Set lighting
  7251. engfunc(EngFunc_LightStyle, 0, lighting)
  7252. }
  7253. }
  7254.  
  7255. // Thunderclap task
  7256. public thunderclap()
  7257. {
  7258. // Play thunder sound
  7259. if (g_lights_i == 0)
  7260. {
  7261. static sound[64]
  7262. ArrayGetString(sound_thunder, random_num(0, ArraySize(sound_thunder) - 1), sound, charsmax(sound))
  7263. PlaySound(sound)
  7264. }
  7265.  
  7266. // Set lighting
  7267. static light[2]
  7268. light[0] = g_lights_cycle[g_lights_i]
  7269. engfunc(EngFunc_LightStyle, 0, light)
  7270.  
  7271. g_lights_i++
  7272.  
  7273. // Lighting cycle end?
  7274. if (g_lights_i >= g_lights_cycle_len)
  7275. {
  7276. remove_task(TASK_THUNDER)
  7277. lighting_effects()
  7278. }
  7279. // Lighting cycle start?
  7280. else if (!task_exists(TASK_THUNDER))
  7281. set_task(0.1, "thunderclap", TASK_THUNDER, _, _, "b")
  7282. }
  7283.  
  7284. // Ambience Sound Effects Task
  7285. public ambience_sound_effects(taskid)
  7286. {
  7287. // Play a random sound depending on the round
  7288. static sound[64], iRand, duration, ismp3
  7289.  
  7290. if (g_nemround) // Nemesis Mode
  7291. {
  7292. iRand = random_num(0, ArraySize(sound_ambience2) - 1)
  7293. ArrayGetString(sound_ambience2, iRand, sound, charsmax(sound))
  7294. duration = ArrayGetCell(sound_ambience2_duration, iRand)
  7295. ismp3 = ArrayGetCell(sound_ambience2_ismp3, iRand)
  7296. }
  7297. else if (g_survround) // Survivor Mode
  7298. {
  7299. iRand = random_num(0, ArraySize(sound_ambience3) - 1)
  7300. ArrayGetString(sound_ambience3, iRand, sound, charsmax(sound))
  7301. duration = ArrayGetCell(sound_ambience3_duration, iRand)
  7302. ismp3 = ArrayGetCell(sound_ambience3_ismp3, iRand)
  7303. }
  7304. else if (g_swarmround) // Swarm Mode
  7305. {
  7306. iRand = random_num(0, ArraySize(sound_ambience4) - 1)
  7307. ArrayGetString(sound_ambience4, iRand, sound, charsmax(sound))
  7308. duration = ArrayGetCell(sound_ambience4_duration, iRand)
  7309. ismp3 = ArrayGetCell(sound_ambience4_ismp3, iRand)
  7310. }
  7311. else if (g_plagueround) // Plague Mode
  7312. {
  7313. iRand = random_num(0, ArraySize(sound_ambience5) - 1)
  7314. ArrayGetString(sound_ambience5, iRand, sound, charsmax(sound))
  7315. duration = ArrayGetCell(sound_ambience5_duration, iRand)
  7316. ismp3 = ArrayGetCell(sound_ambience5_ismp3, iRand)
  7317. }
  7318. else // Infection Mode
  7319. {
  7320. iRand = random_num(0, ArraySize(sound_ambience1) - 1)
  7321. ArrayGetString(sound_ambience1, iRand, sound, charsmax(sound))
  7322. duration = ArrayGetCell(sound_ambience1_duration, iRand)
  7323. ismp3 = ArrayGetCell(sound_ambience1_ismp3, iRand)
  7324. }
  7325.  
  7326. // Play it on clients
  7327. if (ismp3)
  7328. client_cmd(0, "mp3 play ^"sound/%s^"", sound)
  7329. else
  7330. PlaySound(sound)
  7331.  
  7332. // Set the task for when the sound is done playing
  7333. set_task(float(duration), "ambience_sound_effects", TASK_AMBIENCESOUNDS)
  7334. }
  7335.  
  7336. // Ambience Sounds Stop Task
  7337. ambience_sound_stop()
  7338. {
  7339. client_cmd(0, "mp3 stop; stopsound")
  7340. }
  7341.  
  7342. // Flashlight Charge Task
  7343. public flashlight_charge(taskid)
  7344. {
  7345. // Drain or charge?
  7346. if (g_flashlight[ID_CHARGE])
  7347. g_flashbattery[ID_CHARGE] -= get_pcvar_num(cvar_flashdrain)
  7348. else
  7349. g_flashbattery[ID_CHARGE] += get_pcvar_num(cvar_flashcharge)
  7350.  
  7351. // Battery fully charged
  7352. if (g_flashbattery[ID_CHARGE] >= 100)
  7353. {
  7354. // Don't exceed 100%
  7355. g_flashbattery[ID_CHARGE] = 100
  7356.  
  7357. // Update flashlight battery on HUD
  7358. message_begin(MSG_ONE, g_msgFlashBat, _, ID_CHARGE)
  7359. write_byte(100) // battery
  7360. message_end()
  7361.  
  7362. // Task not needed anymore
  7363. remove_task(taskid);
  7364. return;
  7365. }
  7366.  
  7367. // Battery depleted
  7368. if (g_flashbattery[ID_CHARGE] <= 0)
  7369. {
  7370. // Turn it off
  7371. g_flashlight[ID_CHARGE] = false
  7372. g_flashbattery[ID_CHARGE] = 0
  7373.  
  7374. // Play flashlight toggle sound
  7375. emit_sound(ID_CHARGE, CHAN_ITEM, sound_flashlight, 1.0, ATTN_NORM, 0, PITCH_NORM)
  7376.  
  7377. // Update flashlight status on HUD
  7378. message_begin(MSG_ONE, g_msgFlashlight, _, ID_CHARGE)
  7379. write_byte(0) // toggle
  7380. write_byte(0) // battery
  7381. message_end()
  7382.  
  7383. // Remove flashlight task for this player
  7384. remove_task(ID_CHARGE+TASK_FLASH)
  7385. }
  7386. else
  7387. {
  7388. // Update flashlight battery on HUD
  7389. message_begin(MSG_ONE_UNRELIABLE, g_msgFlashBat, _, ID_CHARGE)
  7390. write_byte(g_flashbattery[ID_CHARGE]) // battery
  7391. message_end()
  7392. }
  7393. }
  7394.  
  7395. // Remove Spawn Protection Task
  7396. public remove_spawn_protection(taskid)
  7397. {
  7398. // Not alive
  7399. if (!g_isalive[ID_SPAWN])
  7400. return;
  7401.  
  7402. // Remove spawn protection
  7403. g_nodamage[ID_SPAWN] = false
  7404. set_pev(ID_SPAWN, pev_effects, pev(ID_SPAWN, pev_effects) & ~EF_NODRAW)
  7405. }
  7406.  
  7407. // Hide Player's Money Task
  7408. public task_hide_money(taskid)
  7409. {
  7410. // Not alive
  7411. if (!g_isalive[ID_SPAWN])
  7412. return;
  7413.  
  7414. // Hide money
  7415. message_begin(MSG_ONE, g_msgHideWeapon, _, ID_SPAWN)
  7416. write_byte(HIDE_MONEY) // what to hide bitsum
  7417. message_end()
  7418.  
  7419. // Hide the HL crosshair that's drawn
  7420. message_begin(MSG_ONE, g_msgCrosshair, _, ID_SPAWN)
  7421. write_byte(0) // toggle
  7422. message_end()
  7423. }
  7424.  
  7425. // Turn Off Flashlight and Restore Batteries
  7426. turn_off_flashlight(id)
  7427. {
  7428. // Restore batteries for the next use
  7429. fm_cs_set_user_batteries(id, 100)
  7430.  
  7431. // Check if flashlight is on
  7432. if (pev(id, pev_effects) & EF_DIMLIGHT)
  7433. {
  7434. // Turn it off
  7435. set_pev(id, pev_impulse, IMPULSE_FLASHLIGHT)
  7436. }
  7437. else
  7438. {
  7439. // Clear any stored flashlight impulse (bugfix)
  7440. set_pev(id, pev_impulse, 0)
  7441. }
  7442.  
  7443. // Turn off custom flashlight
  7444. if (g_cached_customflash)
  7445. {
  7446. // Turn it off
  7447. g_flashlight[id] = false
  7448. g_flashbattery[id] = 100
  7449.  
  7450. // Update flashlight HUD
  7451. message_begin(MSG_ONE, g_msgFlashlight, _, id)
  7452. write_byte(0) // toggle
  7453. write_byte(100) // battery
  7454. message_end()
  7455.  
  7456. // Remove previous tasks
  7457. remove_task(id+TASK_CHARGE)
  7458. remove_task(id+TASK_FLASH)
  7459. }
  7460. }
  7461.  
  7462. // Infection Bomb Explosion
  7463. infection_explode(ent)
  7464. {
  7465. // Round ended (bugfix)
  7466. if (g_endround) return;
  7467.  
  7468. // Get origin
  7469. static Float:originF[3]
  7470. pev(ent, pev_origin, originF)
  7471.  
  7472. // Make the explosion
  7473. create_blast(originF)
  7474.  
  7475. // Infection nade explode sound
  7476. static sound[64]
  7477. ArrayGetString(grenade_infect, random_num(0, ArraySize(grenade_infect) - 1), sound, charsmax(sound))
  7478. emit_sound(ent, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  7479.  
  7480. // Get attacker
  7481. static attacker
  7482. attacker = pev(ent, pev_owner)
  7483.  
  7484. // Collisions
  7485. static victim
  7486. victim = -1
  7487.  
  7488. while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, NADE_EXPLOSION_RADIUS)) != 0)
  7489. {
  7490. // Only effect alive non-spawnprotected humans
  7491. if (!is_user_valid_alive(victim) || g_zombie[victim] || g_nodamage[victim])
  7492. continue;
  7493.  
  7494. // Last human is killed
  7495. if (fnGetHumans() == 1)
  7496. {
  7497. ExecuteHamB(Ham_Killed, victim, attacker, 0)
  7498. continue;
  7499. }
  7500.  
  7501. // Infected victim's sound
  7502. ArrayGetString(grenade_infect_player, random_num(0, ArraySize(grenade_infect_player) - 1), sound, charsmax(sound))
  7503. emit_sound(victim, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  7504.  
  7505. // Turn into zombie
  7506. zombieme(victim, attacker, 0, 1, 1)
  7507. }
  7508.  
  7509. // Get rid of the grenade
  7510. engfunc(EngFunc_RemoveEntity, ent)
  7511. }
  7512.  
  7513. // Fire Grenade Explosion
  7514. fire_explode(ent)
  7515. {
  7516. // Get origin
  7517. static Float:originF[3]
  7518. pev(ent, pev_origin, originF)
  7519.  
  7520. // Make the explosion
  7521. create_blast2(originF)
  7522.  
  7523. // Fire nade explode sound
  7524. static sound[64]
  7525. ArrayGetString(grenade_fire, random_num(0, ArraySize(grenade_fire) - 1), sound, charsmax(sound))
  7526. emit_sound(ent, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  7527.  
  7528. // Collisions
  7529. static victim
  7530. victim = -1
  7531.  
  7532. while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, NADE_EXPLOSION_RADIUS)) != 0)
  7533. {
  7534. // Only effect alive zombies
  7535. if (!is_user_valid_alive(victim) || !g_zombie[victim] || g_nodamage[victim])
  7536. continue;
  7537.  
  7538. // Heat icon?
  7539. if (get_pcvar_num(cvar_hudicons))
  7540. {
  7541. message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, _, victim)
  7542. write_byte(0) // damage save
  7543. write_byte(0) // damage take
  7544. write_long(DMG_BURN) // damage type
  7545. write_coord(0) // x
  7546. write_coord(0) // y
  7547. write_coord(0) // z
  7548. message_end()
  7549. }
  7550.  
  7551. if (g_nemesis[victim]) // fire duration (nemesis is fire resistant)
  7552. g_burning_duration[victim] += get_pcvar_num(cvar_fireduration)
  7553. else
  7554. g_burning_duration[victim] += get_pcvar_num(cvar_fireduration) * 5
  7555.  
  7556. // Set burning task on victim if not present
  7557. if (!task_exists(victim+TASK_BURN))
  7558. set_task(0.2, "burning_flame", victim+TASK_BURN, _, _, "b")
  7559. }
  7560.  
  7561. // Get rid of the grenade
  7562. engfunc(EngFunc_RemoveEntity, ent)
  7563. }
  7564.  
  7565. // Frost Grenade Explosion
  7566. frost_explode(ent)
  7567. {
  7568. // Get origin
  7569. static Float:originF[3]
  7570. pev(ent, pev_origin, originF)
  7571.  
  7572. // Make the explosion
  7573. create_blast3(originF)
  7574.  
  7575. // Frost nade explode sound
  7576. static sound[64]
  7577. ArrayGetString(grenade_frost, random_num(0, ArraySize(grenade_frost) - 1), sound, charsmax(sound))
  7578. emit_sound(ent, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  7579.  
  7580. // Collisions
  7581. static victim
  7582. victim = -1
  7583.  
  7584. while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, NADE_EXPLOSION_RADIUS)) != 0)
  7585. {
  7586. // Only effect alive unfrozen zombies
  7587. if (!is_user_valid_alive(victim) || !g_zombie[victim] || g_frozen[victim] || g_nodamage[victim])
  7588. continue;
  7589.  
  7590. // Nemesis shouldn't be frozen
  7591. if (g_nemesis[victim])
  7592. {
  7593. // Get player's origin
  7594. static origin2[3]
  7595. get_user_origin(victim, origin2)
  7596.  
  7597. // Broken glass sound
  7598. ArrayGetString(grenade_frost_break, random_num(0, ArraySize(grenade_frost_break) - 1), sound, charsmax(sound))
  7599. emit_sound(victim, CHAN_BODY, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  7600.  
  7601. // Glass shatter
  7602. message_begin(MSG_PVS, SVC_TEMPENTITY, origin2)
  7603. write_byte(TE_BREAKMODEL) // TE id
  7604. write_coord(origin2[0]) // x
  7605. write_coord(origin2[1]) // y
  7606. write_coord(origin2[2]+24) // z
  7607. write_coord(16) // size x
  7608. write_coord(16) // size y
  7609. write_coord(16) // size z
  7610. write_coord(random_num(-50, 50)) // velocity x
  7611. write_coord(random_num(-50, 50)) // velocity y
  7612. write_coord(25) // velocity z
  7613. write_byte(10) // random velocity
  7614. write_short(g_glassSpr) // model
  7615. write_byte(10) // count
  7616. write_byte(25) // life
  7617. write_byte(BREAK_GLASS) // flags
  7618. message_end()
  7619.  
  7620. continue;
  7621. }
  7622.  
  7623. // Freeze icon?
  7624. if (get_pcvar_num(cvar_hudicons))
  7625. {
  7626. message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, _, victim)
  7627. write_byte(0) // damage save
  7628. write_byte(0) // damage take
  7629. write_long(DMG_DROWN) // damage type - DMG_FREEZE
  7630. write_coord(0) // x
  7631. write_coord(0) // y
  7632. write_coord(0) // z
  7633. message_end()
  7634. }
  7635.  
  7636. // Light blue glow while frozen
  7637. if (g_handle_models_on_separate_ent)
  7638. fm_set_rendering(g_ent_playermodel[victim], kRenderFxGlowShell, 0, 100, 200, kRenderNormal, 25)
  7639. else
  7640. fm_set_rendering(victim, kRenderFxGlowShell, 0, 100, 200, kRenderNormal, 25)
  7641.  
  7642. // Freeze sound
  7643. ArrayGetString(grenade_frost_player, random_num(0, ArraySize(grenade_frost_player) - 1), sound, charsmax(sound))
  7644. emit_sound(victim, CHAN_BODY, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  7645.  
  7646. // Add a blue tint to their screen
  7647. message_begin(MSG_ONE, g_msgScreenFade, _, victim)
  7648. write_short(0) // duration
  7649. write_short(0) // hold time
  7650. write_short(FFADE_STAYOUT) // fade type
  7651. write_byte(0) // red
  7652. write_byte(50) // green
  7653. write_byte(200) // blue
  7654. write_byte(100) // alpha
  7655. message_end()
  7656.  
  7657. // Prevent from jumping
  7658. if (pev(victim, pev_flags) & FL_ONGROUND)
  7659. set_pev(victim, pev_gravity, 999999.9) // set really high
  7660. else
  7661. set_pev(victim, pev_gravity, 0.000001) // no gravity
  7662.  
  7663. // Set a task to remove the freeze
  7664. g_frozen[victim] = true;
  7665. set_task(get_pcvar_float(cvar_freezeduration), "remove_freeze", victim)
  7666. }
  7667.  
  7668. // Get rid of the grenade
  7669. engfunc(EngFunc_RemoveEntity, ent)
  7670. }
  7671.  
  7672. // Remove freeze task
  7673. public remove_freeze(id)
  7674. {
  7675. // Not alive or not frozen anymore
  7676. if (!g_isalive[id] || !g_frozen[id])
  7677. return;
  7678.  
  7679. // Unfreeze
  7680. g_frozen[id] = false;
  7681.  
  7682. // Restore gravity
  7683. if (g_zombie[id])
  7684. {
  7685. if (g_nemesis[id])
  7686. set_pev(id, pev_gravity, get_pcvar_float(cvar_nemgravity))
  7687. else
  7688. set_pev(id, pev_gravity, Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id]))
  7689. }
  7690. else
  7691. {
  7692. if (g_survivor[id])
  7693. set_pev(id, pev_gravity, get_pcvar_float(cvar_survgravity))
  7694. else
  7695. set_pev(id, pev_gravity, get_pcvar_float(cvar_humangravity))
  7696. }
  7697.  
  7698. // Restore rendering
  7699. if (g_handle_models_on_separate_ent)
  7700. {
  7701. // Nemesis or Survivor glow / remove glow on player model entity
  7702. if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
  7703. fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 255, 0, 0, kRenderNormal, 25)
  7704. else if (g_survivor[id] && get_pcvar_num(cvar_survglow))
  7705. fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
  7706. else
  7707. fm_set_rendering(g_ent_playermodel[id])
  7708. }
  7709. else
  7710. {
  7711. // Nemesis or Survivor glow / remove glow
  7712. if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
  7713. fm_set_rendering(id, kRenderFxGlowShell, 255, 0, 0, kRenderNormal, 25)
  7714. else if (g_survivor[id] && get_pcvar_num(cvar_survglow))
  7715. fm_set_rendering(id, kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
  7716. else
  7717. fm_set_rendering(id)
  7718. }
  7719.  
  7720. // Gradually remove screen's blue tint
  7721. message_begin(MSG_ONE, g_msgScreenFade, _, id)
  7722. write_short(UNIT_SECOND) // duration
  7723. write_short(0) // hold time
  7724. write_short(FFADE_IN) // fade type
  7725. write_byte(0) // red
  7726. write_byte(50) // green
  7727. write_byte(200) // blue
  7728. write_byte(100) // alpha
  7729. message_end()
  7730.  
  7731. // Broken glass sound
  7732. static sound[64]
  7733. ArrayGetString(grenade_frost_break, random_num(0, ArraySize(grenade_frost_break) - 1), sound, charsmax(sound))
  7734. emit_sound(id, CHAN_BODY, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  7735.  
  7736. // Get player's origin
  7737. static origin2[3]
  7738. get_user_origin(id, origin2)
  7739.  
  7740. // Glass shatter
  7741. message_begin(MSG_PVS, SVC_TEMPENTITY, origin2)
  7742. write_byte(TE_BREAKMODEL) // TE id
  7743. write_coord(origin2[0]) // x
  7744. write_coord(origin2[1]) // y
  7745. write_coord(origin2[2]+24) // z
  7746. write_coord(16) // size x
  7747. write_coord(16) // size y
  7748. write_coord(16) // size z
  7749. write_coord(random_num(-50, 50)) // velocity x
  7750. write_coord(random_num(-50, 50)) // velocity y
  7751. write_coord(25) // velocity z
  7752. write_byte(10) // random velocity
  7753. write_short(g_glassSpr) // model
  7754. write_byte(10) // count
  7755. write_byte(25) // life
  7756. write_byte(BREAK_GLASS) // flags
  7757. message_end()
  7758.  
  7759. ExecuteForward(g_fwUserUnfrozen, g_fwDummyResult, id);
  7760. }
  7761.  
  7762. // Remove Stuff Task
  7763. public remove_stuff()
  7764. {
  7765. static ent
  7766.  
  7767. // Remove rotating doors
  7768. if (get_pcvar_num(cvar_removedoors) > 0)
  7769. {
  7770. ent = -1;
  7771. while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "func_door_rotating")) != 0)
  7772. engfunc(EngFunc_SetOrigin, ent, Float:{8192.0 ,8192.0 ,8192.0})
  7773. }
  7774.  
  7775. // Remove all doors
  7776. if (get_pcvar_num(cvar_removedoors) > 1)
  7777. {
  7778. ent = -1;
  7779. while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "func_door")) != 0)
  7780. engfunc(EngFunc_SetOrigin, ent, Float:{8192.0 ,8192.0 ,8192.0})
  7781. }
  7782.  
  7783. // Triggered lights
  7784. if (!get_pcvar_num(cvar_triggered))
  7785. {
  7786. ent = -1
  7787. while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "light")) != 0)
  7788. {
  7789. dllfunc(DLLFunc_Use, ent, 0); // turn off the light
  7790. set_pev(ent, pev_targetname, 0) // prevent it from being triggered
  7791. }
  7792. }
  7793. }
  7794.  
  7795. // Set Custom Weapon Models
  7796. replace_weapon_models(id, weaponid)
  7797. {
  7798. switch (weaponid)
  7799. {
  7800. case CSW_KNIFE: // Custom knife models
  7801. {
  7802. if (g_zombie[id])
  7803. {
  7804. if (g_nemesis[id]) // Nemesis
  7805. {
  7806. set_pev(id, pev_viewmodel2, model_vknife_nemesis)
  7807. set_pev(id, pev_weaponmodel2, "")
  7808. }
  7809. else // Zombies
  7810. {
  7811. // Admin knife models?
  7812. if (get_pcvar_num(cvar_adminknifemodelszombie) && get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS])
  7813. {
  7814. set_pev(id, pev_viewmodel2, model_vknife_admin_zombie)
  7815. set_pev(id, pev_weaponmodel2, "")
  7816. }
  7817. else
  7818. {
  7819. static clawmodel[100]
  7820. ArrayGetString(g_zclass_clawmodel, g_zombieclass[id], clawmodel, charsmax(clawmodel))
  7821. format(clawmodel, charsmax(clawmodel), "models/zombie_plague/%s", clawmodel)
  7822. set_pev(id, pev_viewmodel2, clawmodel)
  7823. set_pev(id, pev_weaponmodel2, "")
  7824. }
  7825. }
  7826. }
  7827. else // Humans
  7828. {
  7829. // Admin knife models?
  7830. if (get_pcvar_num(cvar_adminknifemodelshuman) && get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS])
  7831. {
  7832. set_pev(id, pev_viewmodel2, model_vknife_admin_human)
  7833. set_pev(id, pev_weaponmodel2, "")
  7834. }
  7835. else
  7836. {
  7837. set_pev(id, pev_viewmodel2, model_vknife_human)
  7838. set_pev(id, pev_weaponmodel2, "models/p_knife.mdl")
  7839. }
  7840. }
  7841. }
  7842. case CSW_M249: // Survivor's M249
  7843. {
  7844. if (g_survivor[id])
  7845. set_pev(id, pev_viewmodel2, model_vm249_survivor)
  7846. }
  7847. case CSW_HEGRENADE: // Infection bomb or fire grenade
  7848. {
  7849. if (g_zombie[id])
  7850. set_pev(id, pev_viewmodel2, model_grenade_infect)
  7851. else
  7852. set_pev(id, pev_viewmodel2, model_grenade_fire)
  7853. }
  7854. case CSW_FLASHBANG: // Frost grenade
  7855. {
  7856. set_pev(id, pev_viewmodel2, model_grenade_frost)
  7857. }
  7858. case CSW_SMOKEGRENADE: // Flare grenade
  7859. {
  7860. set_pev(id, pev_viewmodel2, model_grenade_flare)
  7861. }
  7862. }
  7863.  
  7864. // Update model on weaponmodel ent
  7865. if (g_handle_models_on_separate_ent) fm_set_weaponmodel_ent(id)
  7866. }
  7867.  
  7868. // Reset Player Vars
  7869. reset_vars(id, resetall)
  7870. {
  7871. g_zombie[id] = false
  7872. g_nemesis[id] = false
  7873. g_survivor[id] = false
  7874. g_firstzombie[id] = false
  7875. g_lastzombie[id] = false
  7876. g_lasthuman[id] = false
  7877. g_frozen[id] = false
  7878. g_nodamage[id] = false
  7879. g_respawn_as_zombie[id] = false
  7880. g_nvision[id] = false
  7881. g_nvisionenabled[id] = false
  7882. g_flashlight[id] = false
  7883. g_flashbattery[id] = 100
  7884. g_canbuy[id] = true
  7885. g_burning_duration[id] = 0
  7886.  
  7887. if (resetall)
  7888. {
  7889. g_ammopacks[id] = get_pcvar_num(cvar_startammopacks)
  7890. g_zombieclass[id] = ZCLASS_NONE
  7891. g_zombieclassnext[id] = ZCLASS_NONE
  7892. g_damagedealt[id] = 0
  7893. WPN_AUTO_ON = 0
  7894. }
  7895. }
  7896.  
  7897. // Set spectators nightvision
  7898. public spec_nvision(id)
  7899. {
  7900. // Not connected, alive, or bot
  7901. if (!g_isconnected[id] || g_isalive[id] || g_isbot[id])
  7902. return;
  7903.  
  7904. // Give Night Vision?
  7905. if (get_pcvar_num(cvar_nvggive))
  7906. {
  7907. g_nvision[id] = true
  7908.  
  7909. // Turn on Night Vision automatically?
  7910. if (get_pcvar_num(cvar_nvggive) == 1)
  7911. {
  7912. g_nvisionenabled[id] = true
  7913.  
  7914. // Custom nvg?
  7915. if (get_pcvar_num(cvar_customnvg))
  7916. {
  7917. remove_task(id+TASK_NVISION)
  7918. set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
  7919. }
  7920. else
  7921. set_user_gnvision(id, 1)
  7922. }
  7923. }
  7924. }
  7925.  
  7926. // Show HUD Task
  7927. public ShowHUD(taskid)
  7928. {
  7929. static id
  7930. id = ID_SHOWHUD;
  7931.  
  7932. // Player died?
  7933. if (!g_isalive[id])
  7934. {
  7935. // Get spectating target
  7936. id = pev(id, PEV_SPEC_TARGET)
  7937.  
  7938. // Target not alive
  7939. if (!g_isalive[id]) return;
  7940. }
  7941.  
  7942. // Format classname
  7943. static class[32], red, green, blue
  7944.  
  7945. if (g_zombie[id]) // zombies
  7946. {
  7947. red = 200
  7948. green = 250
  7949. blue = 0
  7950.  
  7951. if (g_nemesis[id])
  7952. formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_NEMESIS")
  7953. else
  7954. copy(class, charsmax(class), g_zombie_classname[id])
  7955. }
  7956. else // humans
  7957. {
  7958. red = 0
  7959. green = 0
  7960. blue = 255
  7961.  
  7962. if (g_survivor[id])
  7963. formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_SURVIVOR")
  7964. else
  7965. formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_HUMAN")
  7966. }
  7967.  
  7968. // Spectating someone else?
  7969. if (id != ID_SHOWHUD)
  7970. {
  7971. // Show name, health, class, and ammo packs
  7972. set_hudmessage(255, 255, 255, HUD_SPECT_X, HUD_SPECT_Y, 0, 6.0, 1.1, 0.0, 0.0, -1)
  7973. ShowSyncHudMsg(ID_SHOWHUD, g_MsgSync2, "%L %s^nHP: %d - %L %s - %L %d", ID_SHOWHUD, "SPECTATING", g_playername[id], pev(id, pev_health), ID_SHOWHUD, "CLASS_CLASS", class, ID_SHOWHUD, "AMMO_PACKS1", g_ammopacks[id])
  7974. }
  7975. else
  7976. {
  7977. // Show health, class and ammo packs
  7978. set_hudmessage(red, green, blue, HUD_STATS_X, HUD_STATS_Y, 0, 6.0, 1.1, 0.0, 0.0, -1)
  7979. ShowSyncHudMsg(ID_SHOWHUD, g_MsgSync2, "[%L: %d] ^n[%L %s] ^n[%L %d]", id, "ZOMBIE_ATTRIB1", pev(ID_SHOWHUD, pev_health), ID_SHOWHUD, "CLASS_CLASS", class, ID_SHOWHUD, "AMMO_PACKS1", g_ammopacks[ID_SHOWHUD])
  7980. }
  7981. }
  7982.  
  7983. // Play idle zombie sounds
  7984. public zombie_play_idle(taskid)
  7985. {
  7986. // Round ended/new one starting
  7987. if (g_endround || g_newround)
  7988. return;
  7989.  
  7990. static sound[64]
  7991.  
  7992. // Last zombie?
  7993. if (g_lastzombie[ID_BLOOD])
  7994. {
  7995. ArrayGetString(zombie_idle_last, random_num(0, ArraySize(zombie_idle_last) - 1), sound, charsmax(sound))
  7996. emit_sound(ID_BLOOD, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  7997. }
  7998. else
  7999. {
  8000. ArrayGetString(zombie_idle, random_num(0, ArraySize(zombie_idle) - 1), sound, charsmax(sound))
  8001. emit_sound(ID_BLOOD, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  8002. }
  8003. }
  8004.  
  8005. // Madness Over Task
  8006. public madness_over(taskid)
  8007. {
  8008. g_nodamage[ID_BLOOD] = false
  8009. }
  8010.  
  8011. // Place user at a random spawn
  8012. do_random_spawn(id, regularspawns = 0)
  8013. {
  8014. static hull, sp_index, i
  8015.  
  8016. // Get whether the player is crouching
  8017. hull = (pev(id, pev_flags) & FL_DUCKING) ? HULL_HEAD : HULL_HUMAN
  8018.  
  8019. // Use regular spawns?
  8020. if (!regularspawns)
  8021. {
  8022. // No spawns?
  8023. if (!g_spawnCount)
  8024. return;
  8025.  
  8026. // Choose random spawn to start looping at
  8027. sp_index = random_num(0, g_spawnCount - 1)
  8028.  
  8029. // Try to find a clear spawn
  8030. for (i = sp_index + 1; /*no condition*/; i++)
  8031. {
  8032. // Start over when we reach the end
  8033. if (i >= g_spawnCount) i = 0
  8034.  
  8035. // Free spawn space?
  8036. if (is_hull_vacant(g_spawns[i], hull))
  8037. {
  8038. // Engfunc_SetOrigin is used so ent's mins and maxs get updated instantly
  8039. engfunc(EngFunc_SetOrigin, id, g_spawns[i])
  8040. break;
  8041. }
  8042.  
  8043. // Loop completed, no free space found
  8044. if (i == sp_index) break;
  8045. }
  8046. }
  8047. else
  8048. {
  8049. // No spawns?
  8050. if (!g_spawnCount2)
  8051. return;
  8052.  
  8053. // Choose random spawn to start looping at
  8054. sp_index = random_num(0, g_spawnCount2 - 1)
  8055.  
  8056. // Try to find a clear spawn
  8057. for (i = sp_index + 1; /*no condition*/; i++)
  8058. {
  8059. // Start over when we reach the end
  8060. if (i >= g_spawnCount2) i = 0
  8061.  
  8062. // Free spawn space?
  8063. if (is_hull_vacant(g_spawns2[i], hull))
  8064. {
  8065. // Engfunc_SetOrigin is used so ent's mins and maxs get updated instantly
  8066. engfunc(EngFunc_SetOrigin, id, g_spawns2[i])
  8067. break;
  8068. }
  8069.  
  8070. // Loop completed, no free space found
  8071. if (i == sp_index) break;
  8072. }
  8073. }
  8074. }
  8075.  
  8076. // Get Zombies -returns alive zombies number-
  8077. fnGetZombies()
  8078. {
  8079. static iZombies, id
  8080. iZombies = 0
  8081.  
  8082. for (id = 1; id <= g_maxplayers; id++)
  8083. {
  8084. if (g_isalive[id] && g_zombie[id])
  8085. iZombies++
  8086. }
  8087.  
  8088. return iZombies;
  8089. }
  8090.  
  8091. // Get Humans -returns alive humans number-
  8092. fnGetHumans()
  8093. {
  8094. static iHumans, id
  8095. iHumans = 0
  8096.  
  8097. for (id = 1; id <= g_maxplayers; id++)
  8098. {
  8099. if (g_isalive[id] && !g_zombie[id])
  8100. iHumans++
  8101. }
  8102.  
  8103. return iHumans;
  8104. }
  8105.  
  8106. // Get Nemesis -returns alive nemesis number-
  8107. fnGetNemesis()
  8108. {
  8109. static iNemesis, id
  8110. iNemesis = 0
  8111.  
  8112. for (id = 1; id <= g_maxplayers; id++)
  8113. {
  8114. if (g_isalive[id] && g_nemesis[id])
  8115. iNemesis++
  8116. }
  8117.  
  8118. return iNemesis;
  8119. }
  8120.  
  8121. // Get Survivors -returns alive survivors number-
  8122. fnGetSurvivors()
  8123. {
  8124. static iSurvivors, id
  8125. iSurvivors = 0
  8126.  
  8127. for (id = 1; id <= g_maxplayers; id++)
  8128. {
  8129. if (g_isalive[id] && g_survivor[id])
  8130. iSurvivors++
  8131. }
  8132.  
  8133. return iSurvivors;
  8134. }
  8135.  
  8136. // Get Alive -returns alive players number-
  8137. fnGetAlive()
  8138. {
  8139. static iAlive, id
  8140. iAlive = 0
  8141.  
  8142. for (id = 1; id <= g_maxplayers; id++)
  8143. {
  8144. if (g_isalive[id])
  8145. iAlive++
  8146. }
  8147.  
  8148. return iAlive;
  8149. }
  8150.  
  8151. // Get Random Alive -returns index of alive player number n -
  8152. fnGetRandomAlive(n)
  8153. {
  8154. static iAlive, id
  8155. iAlive = 0
  8156.  
  8157. for (id = 1; id <= g_maxplayers; id++)
  8158. {
  8159. if (g_isalive[id])
  8160. iAlive++
  8161.  
  8162. if (iAlive == n)
  8163. return id;
  8164. }
  8165.  
  8166. return -1;
  8167. }
  8168.  
  8169. // Get Playing -returns number of users playing-
  8170. fnGetPlaying()
  8171. {
  8172. static iPlaying, id, team
  8173. iPlaying = 0
  8174.  
  8175. for (id = 1; id <= g_maxplayers; id++)
  8176. {
  8177. if (g_isconnected[id])
  8178. {
  8179. team = fm_cs_get_user_team(id)
  8180.  
  8181. if (team != FM_CS_TEAM_SPECTATOR && team != FM_CS_TEAM_UNASSIGNED)
  8182. iPlaying++
  8183. }
  8184. }
  8185.  
  8186. return iPlaying;
  8187. }
  8188.  
  8189. // Get CTs -returns number of CTs connected-
  8190. fnGetCTs()
  8191. {
  8192. static iCTs, id
  8193. iCTs = 0
  8194.  
  8195. for (id = 1; id <= g_maxplayers; id++)
  8196. {
  8197. if (g_isconnected[id])
  8198. {
  8199. if (fm_cs_get_user_team(id) == FM_CS_TEAM_CT)
  8200. iCTs++
  8201. }
  8202. }
  8203.  
  8204. return iCTs;
  8205. }
  8206.  
  8207. // Get Ts -returns number of Ts connected-
  8208. fnGetTs()
  8209. {
  8210. static iTs, id
  8211. iTs = 0
  8212.  
  8213. for (id = 1; id <= g_maxplayers; id++)
  8214. {
  8215. if (g_isconnected[id])
  8216. {
  8217. if (fm_cs_get_user_team(id) == FM_CS_TEAM_T)
  8218. iTs++
  8219. }
  8220. }
  8221.  
  8222. return iTs;
  8223. }
  8224.  
  8225. // Get Alive CTs -returns number of CTs alive-
  8226. fnGetAliveCTs()
  8227. {
  8228. static iCTs, id
  8229. iCTs = 0
  8230.  
  8231. for (id = 1; id <= g_maxplayers; id++)
  8232. {
  8233. if (g_isalive[id])
  8234. {
  8235. if (fm_cs_get_user_team(id) == FM_CS_TEAM_CT)
  8236. iCTs++
  8237. }
  8238. }
  8239.  
  8240. return iCTs;
  8241. }
  8242.  
  8243. // Get Alive Ts -returns number of Ts alive-
  8244. fnGetAliveTs()
  8245. {
  8246. static iTs, id
  8247. iTs = 0
  8248.  
  8249. for (id = 1; id <= g_maxplayers; id++)
  8250. {
  8251. if (g_isalive[id])
  8252. {
  8253. if (fm_cs_get_user_team(id) == FM_CS_TEAM_T)
  8254. iTs++
  8255. }
  8256. }
  8257.  
  8258. return iTs;
  8259. }
  8260.  
  8261. // Last Zombie Check -check for last zombie and set its flag-
  8262. fnCheckLastZombie()
  8263. {
  8264. static id
  8265. for (id = 1; id <= g_maxplayers; id++)
  8266. {
  8267. // Last zombie
  8268. if (g_isalive[id] && g_zombie[id] && !g_nemesis[id] && fnGetZombies() == 1)
  8269. {
  8270. if (!g_lastzombie[id])
  8271. {
  8272. // Last zombie forward
  8273. ExecuteForward(g_fwUserLastZombie, g_fwDummyResult, id);
  8274. }
  8275. g_lastzombie[id] = true
  8276. }
  8277. else
  8278. g_lastzombie[id] = false
  8279.  
  8280. // Last human
  8281. if (g_isalive[id] && !g_zombie[id] && !g_survivor[id] && fnGetHumans() == 1)
  8282. {
  8283. if (!g_lasthuman[id])
  8284. {
  8285. // Last human forward
  8286. ExecuteForward(g_fwUserLastHuman, g_fwDummyResult, id);
  8287.  
  8288. // Reward extra hp
  8289. fm_set_user_health(id, pev(id, pev_health) + get_pcvar_num(cvar_humanlasthp))
  8290. }
  8291. g_lasthuman[id] = true
  8292. }
  8293. else
  8294. g_lasthuman[id] = false
  8295. }
  8296. }
  8297.  
  8298. // Save player's stats to database
  8299. save_stats(id)
  8300. {
  8301. // Check whether there is another record already in that slot
  8302. if (db_name[id][0] && !equal(g_playername[id], db_name[id]))
  8303. {
  8304. // If DB size is exceeded, write over old records
  8305. if (db_slot_i >= sizeof db_name)
  8306. db_slot_i = g_maxplayers+1
  8307.  
  8308. // Move previous record onto an additional save slot
  8309. copy(db_name[db_slot_i], charsmax(db_name[]), db_name[id])
  8310. db_ammopacks[db_slot_i] = db_ammopacks[id]
  8311. db_zombieclass[db_slot_i] = db_zombieclass[id]
  8312. db_slot_i++
  8313. }
  8314.  
  8315. // Now save the current player stats
  8316. copy(db_name[id], charsmax(db_name[]), g_playername[id]) // name
  8317. db_ammopacks[id] = g_ammopacks[id] // ammo packs
  8318. db_zombieclass[id] = g_zombieclassnext[id] // zombie class
  8319. }
  8320.  
  8321. // Load player's stats from database (if a record is found)
  8322. load_stats(id)
  8323. {
  8324. // Look for a matching record
  8325. static i
  8326. for (i = 0; i < sizeof db_name; i++)
  8327. {
  8328. if (equal(g_playername[id], db_name[i]))
  8329. {
  8330. // Bingo!
  8331. g_ammopacks[id] = db_ammopacks[i]
  8332. g_zombieclass[id] = db_zombieclass[i]
  8333. g_zombieclassnext[id] = db_zombieclass[i]
  8334. return;
  8335. }
  8336. }
  8337. }
  8338.  
  8339. // Checks if a player is allowed to be zombie
  8340. allowed_zombie(id)
  8341. {
  8342. if ((g_zombie[id] && !g_nemesis[id]) || g_endround || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && !g_zombie[id] && fnGetHumans() == 1))
  8343. return false;
  8344.  
  8345. return true;
  8346. }
  8347.  
  8348. // Checks if a player is allowed to be human
  8349. allowed_human(id)
  8350. {
  8351. if ((!g_zombie[id] && !g_survivor[id]) || g_endround || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && g_zombie[id] && fnGetZombies() == 1))
  8352. return false;
  8353.  
  8354. return true;
  8355. }
  8356.  
  8357. // Checks if a player is allowed to be survivor
  8358. allowed_survivor(id)
  8359. {
  8360. if (g_endround || g_survivor[id] || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && g_zombie[id] && fnGetZombies() == 1))
  8361. return false;
  8362.  
  8363. return true;
  8364. }
  8365.  
  8366. // Checks if a player is allowed to be nemesis
  8367. allowed_nemesis(id)
  8368. {
  8369. if (g_endround || g_nemesis[id] || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && !g_zombie[id] && fnGetHumans() == 1))
  8370. return false;
  8371.  
  8372. return true;
  8373. }
  8374.  
  8375. // Checks if a player is allowed to respawn
  8376. allowed_respawn(id)
  8377. {
  8378. static team
  8379. team = fm_cs_get_user_team(id)
  8380.  
  8381. if (g_endround || team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED || g_isalive[id])
  8382. return false;
  8383.  
  8384. return true;
  8385. }
  8386.  
  8387. // Checks if swarm mode is allowed
  8388. allowed_swarm()
  8389. {
  8390. if (g_endround || !g_newround || task_exists(TASK_WELCOMEMSG))
  8391. return false;
  8392.  
  8393. return true;
  8394. }
  8395.  
  8396. // Checks if multi infection mode is allowed
  8397. allowed_multi()
  8398. {
  8399. if (g_endround || !g_newround || task_exists(TASK_WELCOMEMSG) || floatround(fnGetAlive()*get_pcvar_float(cvar_multiratio), floatround_ceil) < 2 || floatround(fnGetAlive()*get_pcvar_float(cvar_multiratio), floatround_ceil) >= fnGetAlive())
  8400. return false;
  8401.  
  8402. return true;
  8403. }
  8404.  
  8405. // Checks if plague mode is allowed
  8406. allowed_plague()
  8407. {
  8408. if (g_endround || !g_newround || task_exists(TASK_WELCOMEMSG) || floatround((fnGetAlive()-(get_pcvar_num(cvar_plaguenemnum)+get_pcvar_num(cvar_plaguesurvnum)))*get_pcvar_float(cvar_plagueratio), floatround_ceil) < 1
  8409. || fnGetAlive()-(get_pcvar_num(cvar_plaguesurvnum)+get_pcvar_num(cvar_plaguenemnum)+floatround((fnGetAlive()-(get_pcvar_num(cvar_plaguenemnum)+get_pcvar_num(cvar_plaguesurvnum)))*get_pcvar_float(cvar_plagueratio), floatround_ceil)) < 1)
  8410. return false;
  8411.  
  8412. return true;
  8413. }
  8414.  
  8415. // Admin Command. zp_zombie
  8416. command_zombie(id, player)
  8417. {
  8418. // Show activity?
  8419. switch (get_pcvar_num(cvar_showactivity))
  8420. {
  8421. case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_INFECT")
  8422. case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_INFECT")
  8423. }
  8424.  
  8425. // Log to Zombie Plague log file?
  8426. if (get_pcvar_num(cvar_logcommands))
  8427. {
  8428. static logdata[100], authid[32], ip[16]
  8429. get_user_authid(id, authid, charsmax(authid))
  8430. get_user_ip(id, ip, charsmax(ip), 1)
  8431. formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %s %L (Players: %d/%d)", g_playername[id], authid, ip, g_playername[player], LANG_SERVER, "CMD_INFECT", fnGetPlaying(), g_maxplayers)
  8432. log_to_file("zombieplague.log", logdata)
  8433. }
  8434.  
  8435. // New round?
  8436. if (g_newround)
  8437. {
  8438. // Set as first zombie
  8439. remove_task(TASK_MAKEZOMBIE)
  8440. make_a_zombie(MODE_INFECTION, player)
  8441. }
  8442. else
  8443. {
  8444. // Just infect
  8445. zombieme(player, 0, 0, 0, 0)
  8446. }
  8447. }
  8448.  
  8449. // Admin Command. zp_human
  8450. command_human(id, player)
  8451. {
  8452. // Show activity?
  8453. switch (get_pcvar_num(cvar_showactivity))
  8454. {
  8455. case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_DISINFECT")
  8456. case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_DISINFECT")
  8457. }
  8458.  
  8459. // Log to Zombie Plague log file?
  8460. if (get_pcvar_num(cvar_logcommands))
  8461. {
  8462. static logdata[100], authid[32], ip[16]
  8463. get_user_authid(id, authid, charsmax(authid))
  8464. get_user_ip(id, ip, charsmax(ip), 1)
  8465. formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %s %L (Players: %d/%d)", g_playername[id], authid, ip, g_playername[player], LANG_SERVER,"CMD_DISINFECT", fnGetPlaying(), g_maxplayers)
  8466. log_to_file("zombieplague.log", logdata)
  8467. }
  8468.  
  8469. // Turn to human
  8470. humanme(player, 0, 0)
  8471. }
  8472.  
  8473. // Admin Command. zp_survivor
  8474. command_survivor(id, player)
  8475. {
  8476. // Show activity?
  8477. switch (get_pcvar_num(cvar_showactivity))
  8478. {
  8479. case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_SURVIVAL")
  8480. case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_SURVIVAL")
  8481. }
  8482.  
  8483. // Log to Zombie Plague log file?
  8484. if (get_pcvar_num(cvar_logcommands))
  8485. {
  8486. static logdata[100], authid[32], ip[16]
  8487. get_user_authid(id, authid, charsmax(authid))
  8488. get_user_ip(id, ip, charsmax(ip), 1)
  8489. formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %s %L (Players: %d/%d)", g_playername[id], authid, ip, g_playername[player], LANG_SERVER,"CMD_SURVIVAL", fnGetPlaying(), g_maxplayers)
  8490. log_to_file("zombieplague.log", logdata)
  8491. }
  8492.  
  8493. // New round?
  8494. if (g_newround)
  8495. {
  8496. // Set as first survivor
  8497. remove_task(TASK_MAKEZOMBIE)
  8498. make_a_zombie(MODE_SURVIVOR, player)
  8499. }
  8500. else
  8501. {
  8502. // Turn player into a Survivor
  8503. humanme(player, 1, 0)
  8504. }
  8505. }
  8506.  
  8507. // Admin Command. zp_nemesis
  8508. command_nemesis(id, player)
  8509. {
  8510. // Show activity?
  8511. switch (get_pcvar_num(cvar_showactivity))
  8512. {
  8513. case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_NEMESIS")
  8514. case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_NEMESIS")
  8515. }
  8516.  
  8517. // Log to Zombie Plague log file?
  8518. if (get_pcvar_num(cvar_logcommands))
  8519. {
  8520. static logdata[100], authid[32], ip[16]
  8521. get_user_authid(id, authid, charsmax(authid))
  8522. get_user_ip(id, ip, charsmax(ip), 1)
  8523. formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %s %L (Players: %d/%d)", g_playername[id], authid, ip, g_playername[player], LANG_SERVER,"CMD_NEMESIS", fnGetPlaying(), g_maxplayers)
  8524. log_to_file("zombieplague.log", logdata)
  8525. }
  8526.  
  8527. // New round?
  8528. if (g_newround)
  8529. {
  8530. // Set as first nemesis
  8531. remove_task(TASK_MAKEZOMBIE)
  8532. make_a_zombie(MODE_NEMESIS, player)
  8533. }
  8534. else
  8535. {
  8536. // Turn player into a Nemesis
  8537. zombieme(player, 0, 1, 0, 0)
  8538. }
  8539. }
  8540.  
  8541. // Admin Command. zp_respawn
  8542. command_respawn(id, player)
  8543. {
  8544. // Show activity?
  8545. switch (get_pcvar_num(cvar_showactivity))
  8546. {
  8547. case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_RESPAWN")
  8548. case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_RESPAWN")
  8549. }
  8550.  
  8551. // Log to Zombie Plague log file?
  8552. if (get_pcvar_num(cvar_logcommands))
  8553. {
  8554. static logdata[100], authid[32], ip[16]
  8555. get_user_authid(id, authid, charsmax(authid))
  8556. get_user_ip(id, ip, charsmax(ip), 1)
  8557. formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %s %L (Players: %d/%d)", g_playername[id], authid, ip, g_playername[player], LANG_SERVER, "CMD_RESPAWN", fnGetPlaying(), g_maxplayers)
  8558. log_to_file("zombieplague.log", logdata)
  8559. }
  8560.  
  8561. // Respawn as zombie?
  8562. if (get_pcvar_num(cvar_deathmatch) == 2 || (get_pcvar_num(cvar_deathmatch) == 3 && random_num(0, 1)) || (get_pcvar_num(cvar_deathmatch) == 4 && fnGetZombies() < fnGetAlive()/2))
  8563. g_respawn_as_zombie[player] = true
  8564.  
  8565. // Override respawn as zombie setting on nemesis and survivor rounds
  8566. if (g_survround) g_respawn_as_zombie[player] = true
  8567. else if (g_nemround) g_respawn_as_zombie[player] = false
  8568.  
  8569. respawn_player_manually(player);
  8570. }
  8571.  
  8572. // Admin Command. zp_swarm
  8573. command_swarm(id)
  8574. {
  8575. // Show activity?
  8576. switch (get_pcvar_num(cvar_showactivity))
  8577. {
  8578. case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_SWARM")
  8579. case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_SWARM")
  8580. }
  8581.  
  8582. // Log to Zombie Plague log file?
  8583. if (get_pcvar_num(cvar_logcommands))
  8584. {
  8585. static logdata[100], authid[32], ip[16]
  8586. get_user_authid(id, authid, charsmax(authid))
  8587. get_user_ip(id, ip, charsmax(ip), 1)
  8588. formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER, "CMD_SWARM", fnGetPlaying(), g_maxplayers)
  8589. log_to_file("zombieplague.log", logdata)
  8590. }
  8591.  
  8592. // Call Swarm Mode
  8593. remove_task(TASK_MAKEZOMBIE)
  8594. make_a_zombie(MODE_SWARM, 0)
  8595. }
  8596.  
  8597. // Admin Command. zp_multi
  8598. command_multi(id)
  8599. {
  8600. // Show activity?
  8601. switch (get_pcvar_num(cvar_showactivity))
  8602. {
  8603. case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_MULTI")
  8604. case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_MULTI")
  8605. }
  8606.  
  8607. // Log to Zombie Plague log file?
  8608. if (get_pcvar_num(cvar_logcommands))
  8609. {
  8610. static logdata[100], authid[32], ip[16]
  8611. get_user_authid(id, authid, charsmax(authid))
  8612. get_user_ip(id, ip, charsmax(ip), 1)
  8613. formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_MULTI", fnGetPlaying(), g_maxplayers)
  8614. log_to_file("zombieplague.log", logdata)
  8615. }
  8616.  
  8617. // Call Multi Infection
  8618. remove_task(TASK_MAKEZOMBIE)
  8619. make_a_zombie(MODE_MULTI, 0)
  8620. }
  8621.  
  8622. // Admin Command. zp_plague
  8623. command_plague(id)
  8624. {
  8625. // Show activity?
  8626. switch (get_pcvar_num(cvar_showactivity))
  8627. {
  8628. case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_PLAGUE")
  8629. case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_PLAGUE")
  8630. }
  8631.  
  8632. // Log to Zombie Plague log file?
  8633. if (get_pcvar_num(cvar_logcommands))
  8634. {
  8635. static logdata[100], authid[32], ip[16]
  8636. get_user_authid(id, authid, charsmax(authid))
  8637. get_user_ip(id, ip, charsmax(ip), 1)
  8638. formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_PLAGUE", fnGetPlaying(), g_maxplayers)
  8639. log_to_file("zombieplague.log", logdata)
  8640. }
  8641.  
  8642. // Call Plague Mode
  8643. remove_task(TASK_MAKEZOMBIE)
  8644. make_a_zombie(MODE_PLAGUE, 0)
  8645. }
  8646.  
  8647. /*================================================================================
  8648. [Custom Natives]
  8649. =================================================================================*/
  8650.  
  8651. // Native: zp_get_user_zombie
  8652. public native_get_user_zombie(id)
  8653. {
  8654. return g_zombie[id];
  8655. }
  8656.  
  8657. // Native: zp_get_user_nemesis
  8658. public native_get_user_nemesis(id)
  8659. {
  8660. return g_nemesis[id];
  8661. }
  8662.  
  8663. // Native: zp_get_user_survivor
  8664. public native_get_user_survivor(id)
  8665. {
  8666. return g_survivor[id];
  8667. }
  8668.  
  8669. public native_get_user_first_zombie(id)
  8670. {
  8671. return g_firstzombie[id];
  8672. }
  8673.  
  8674. // Native: zp_get_user_last_zombie
  8675. public native_get_user_last_zombie(id)
  8676. {
  8677. return g_lastzombie[id];
  8678. }
  8679.  
  8680. // Native: zp_get_user_last_human
  8681. public native_get_user_last_human(id)
  8682. {
  8683. return g_lasthuman[id];
  8684. }
  8685.  
  8686. // Native: zp_get_user_zombie_class
  8687. public native_get_user_zombie_class(id)
  8688. {
  8689. return g_zombieclass[id];
  8690. }
  8691.  
  8692. // Native: zp_get_user_next_class
  8693. public native_get_user_next_class(id)
  8694. {
  8695. return g_zombieclassnext[id];
  8696. }
  8697.  
  8698. // Native: zp_set_user_zombie_class
  8699. public native_set_user_zombie_class(id, classid)
  8700. {
  8701. if (classid < 0 || classid >= g_zclass_i)
  8702. return 0;
  8703.  
  8704. g_zombieclassnext[id] = classid
  8705. return 1;
  8706. }
  8707.  
  8708. // Native: zp_get_user_ammo_packs
  8709. public native_get_user_ammo_packs(id)
  8710. {
  8711. return g_ammopacks[id];
  8712. }
  8713.  
  8714. // Native: zp_set_user_ammo_packs
  8715. public native_set_user_ammo_packs(id, amount)
  8716. {
  8717. g_ammopacks[id] = amount;
  8718. }
  8719.  
  8720. // Native: zp_get_zombie_maxhealth
  8721. public native_get_zombie_maxhealth(id)
  8722. {
  8723. // ZP disabled
  8724. if (!g_pluginenabled)
  8725. return -1;
  8726.  
  8727. if (g_zombie[id] && !g_nemesis[id])
  8728. {
  8729. if (g_firstzombie[id])
  8730. return floatround(float(ArrayGetCell(g_zclass_hp, g_zombieclass[id])) * get_pcvar_float(cvar_zombiefirsthp));
  8731. else
  8732. return ArrayGetCell(g_zclass_hp, g_zombieclass[id]);
  8733. }
  8734. return -1;
  8735. }
  8736.  
  8737. // Native: zp_get_user_batteries
  8738. public native_get_user_batteries(id)
  8739. {
  8740. return g_flashbattery[id];
  8741. }
  8742.  
  8743. // Native: zp_set_user_batteries
  8744. public native_set_user_batteries(id, value)
  8745. {
  8746. // ZP disabled
  8747. if (!g_pluginenabled)
  8748. return;
  8749.  
  8750. g_flashbattery[id] = clamp(value, 0, 100);
  8751.  
  8752. if (g_cached_customflash)
  8753. {
  8754. // Set the flashlight charge task to update battery status
  8755. remove_task(id+TASK_CHARGE)
  8756. set_task(1.0, "flashlight_charge", id+TASK_CHARGE, _, _, "b")
  8757. }
  8758. }
  8759.  
  8760. // Native: zp_get_user_nightvision
  8761. public native_get_user_nightvision(id)
  8762. {
  8763. return g_nvision[id];
  8764. }
  8765.  
  8766. // Native: zp_set_user_nightvision
  8767. public native_set_user_nightvision(id, set)
  8768. {
  8769. // ZP disabled
  8770. if (!g_pluginenabled)
  8771. return;
  8772.  
  8773. if (set)
  8774. {
  8775. g_nvision[id] = true
  8776.  
  8777. if (!g_isbot[id])
  8778. {
  8779. g_nvisionenabled[id] = true
  8780.  
  8781. // Custom nvg?
  8782. if (get_pcvar_num(cvar_customnvg))
  8783. {
  8784. remove_task(id+TASK_NVISION)
  8785. set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
  8786. }
  8787. else
  8788. set_user_gnvision(id, 1)
  8789. }
  8790. else
  8791. cs_set_user_nvg(id, 1)
  8792. }
  8793. else
  8794. {
  8795. // Turn off NVG for bots
  8796. if (g_isbot[id]) cs_set_user_nvg(id, 0);
  8797. if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
  8798. else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
  8799. g_nvision[id] = false
  8800. g_nvisionenabled[id] = false
  8801. }
  8802. }
  8803.  
  8804. // Native: zp_infect_user
  8805. public native_infect_user(id, infector, silent, rewards)
  8806. {
  8807. // ZP disabled
  8808. if (!g_pluginenabled)
  8809. return -1;
  8810.  
  8811. // Not allowed to be zombie
  8812. if (!allowed_zombie(id))
  8813. return 0;
  8814.  
  8815. // New round?
  8816. if (g_newround)
  8817. {
  8818. // Set as first zombie
  8819. remove_task(TASK_MAKEZOMBIE)
  8820. make_a_zombie(MODE_INFECTION, id)
  8821. }
  8822. else
  8823. {
  8824. // Just infect (plus some checks)
  8825. zombieme(id, is_user_valid_alive(infector) ? infector : 0, 0, (silent == 1) ? 1 : 0, (rewards == 1) ? 1 : 0)
  8826. }
  8827.  
  8828. return 1;
  8829. }
  8830.  
  8831. // Native: zp_disinfect_user
  8832. public native_disinfect_user(id, silent)
  8833. {
  8834. // ZP disabled
  8835. if (!g_pluginenabled)
  8836. return -1;
  8837.  
  8838. // Not allowed to be human
  8839. if (!allowed_human(id))
  8840. return 0;
  8841.  
  8842. // Turn to human
  8843. humanme(id, 0, (silent == 1) ? 1 : 0)
  8844. return 1;
  8845. }
  8846.  
  8847. // Native: zp_make_user_nemesis
  8848. public native_make_user_nemesis(id)
  8849. {
  8850. // ZP disabled
  8851. if (!g_pluginenabled)
  8852. return -1;
  8853.  
  8854. // Not allowed to be nemesis
  8855. if (!allowed_nemesis(id))
  8856. return 0;
  8857.  
  8858. // New round?
  8859. if (g_newround)
  8860. {
  8861. // Set as first nemesis
  8862. remove_task(TASK_MAKEZOMBIE)
  8863. make_a_zombie(MODE_NEMESIS, id)
  8864. }
  8865. else
  8866. {
  8867. // Turn player into a Nemesis
  8868. zombieme(id, 0, 1, 0, 0)
  8869. }
  8870.  
  8871. return 1;
  8872. }
  8873.  
  8874. // Native: zp_make_user_survivor
  8875. public native_make_user_survivor(id)
  8876. {
  8877. // ZP disabled
  8878. if (!g_pluginenabled)
  8879. return -1;
  8880.  
  8881. // Not allowed to be survivor
  8882. if (!allowed_survivor(id))
  8883. return 0;
  8884.  
  8885. // New round?
  8886. if (g_newround)
  8887. {
  8888. // Set as first survivor
  8889. remove_task(TASK_MAKEZOMBIE)
  8890. make_a_zombie(MODE_SURVIVOR, id)
  8891. }
  8892. else
  8893. {
  8894. // Turn player into a Survivor
  8895. humanme(id, 1, 0)
  8896. }
  8897.  
  8898. return 1;
  8899. }
  8900.  
  8901. // Native: zp_respawn_user
  8902. public native_respawn_user(id, team)
  8903. {
  8904. // ZP disabled
  8905. if (!g_pluginenabled)
  8906. return -1;
  8907.  
  8908. // Invalid player
  8909. if (!is_user_valid_connected(id))
  8910. return 0;
  8911.  
  8912. // Respawn not allowed
  8913. if (!allowed_respawn(id))
  8914. return 0;
  8915.  
  8916. // Respawn as zombie?
  8917. g_respawn_as_zombie[id] = (team == ZP_TEAM_ZOMBIE) ? true : false
  8918.  
  8919. // Respawnish!
  8920. respawn_player_manually(id)
  8921. return 1;
  8922. }
  8923.  
  8924. // Native: zp_force_buy_extra_item
  8925. public native_force_buy_extra_item(id, itemid, ignorecost)
  8926. {
  8927. // ZP disabled
  8928. if (!g_pluginenabled)
  8929. return -1;
  8930.  
  8931. if (itemid < 0 || itemid >= g_extraitem_i)
  8932. return 0;
  8933.  
  8934. buy_extra_item(id, itemid, ignorecost)
  8935. return 1;
  8936. }
  8937.  
  8938. // Native: zp_has_round_started
  8939. public native_has_round_started()
  8940. {
  8941. if (g_newround) return 0; // not started
  8942. if (g_modestarted) return 1; // started
  8943. return 2; // starting
  8944. }
  8945.  
  8946. // Native: zp_is_nemesis_round
  8947. public native_is_nemesis_round()
  8948. {
  8949. return g_nemround;
  8950. }
  8951.  
  8952. // Native: zp_is_survivor_round
  8953. public native_is_survivor_round()
  8954. {
  8955. return g_survround;
  8956. }
  8957.  
  8958. // Native: zp_is_swarm_round
  8959. public native_is_swarm_round()
  8960. {
  8961. return g_swarmround;
  8962. }
  8963.  
  8964. // Native: zp_is_plague_round
  8965. public native_is_plague_round()
  8966. {
  8967. return g_plagueround;
  8968. }
  8969.  
  8970. // Native: zp_get_zombie_count
  8971. public native_get_zombie_count()
  8972. {
  8973. return fnGetZombies();
  8974. }
  8975.  
  8976. // Native: zp_get_human_count
  8977. public native_get_human_count()
  8978. {
  8979. return fnGetHumans();
  8980. }
  8981.  
  8982. // Native: zp_get_nemesis_count
  8983. public native_get_nemesis_count()
  8984. {
  8985. return fnGetNemesis();
  8986. }
  8987.  
  8988. // Native: zp_get_survivor_count
  8989. public native_get_survivor_count()
  8990. {
  8991. return fnGetSurvivors();
  8992. }
  8993.  
  8994. // Native: zp_register_extra_item
  8995. public native_register_extra_item(const name[], cost, team)
  8996. {
  8997. // ZP disabled
  8998. if (!g_pluginenabled)
  8999. return -1;
  9000.  
  9001. // Arrays not yet initialized
  9002. if (!g_arrays_created)
  9003. return -1;
  9004.  
  9005. // For backwards compatibility
  9006. if (team == ZP_TEAM_ANY)
  9007. team = ZP_TEAM_ZOMBIE|ZP_TEAM_HUMAN
  9008.  
  9009. // Strings passed byref
  9010. param_convert(1)
  9011.  
  9012. // Add the item
  9013. ArrayPushString(g_extraitem_name, name)
  9014. ArrayPushCell(g_extraitem_cost, cost)
  9015. ArrayPushCell(g_extraitem_team, team)
  9016.  
  9017. // Set temporary new item flag
  9018. ArrayPushCell(g_extraitem_new, 1)
  9019.  
  9020. // Override extra items data with our customizations
  9021. new i, buffer[32], size = ArraySize(g_extraitem2_realname)
  9022. for (i = 0; i < size; i++)
  9023. {
  9024. ArrayGetString(g_extraitem2_realname, i, buffer, charsmax(buffer))
  9025.  
  9026. // Check if this is the intended item to override
  9027. if (!equal(name, buffer))
  9028. continue;
  9029.  
  9030. // Remove new item flag
  9031. ArraySetCell(g_extraitem_new, g_extraitem_i, 0)
  9032.  
  9033. // Replace caption
  9034. ArrayGetString(g_extraitem2_name, i, buffer, charsmax(buffer))
  9035. ArraySetString(g_extraitem_name, g_extraitem_i, buffer)
  9036.  
  9037. // Replace cost
  9038. buffer[0] = ArrayGetCell(g_extraitem2_cost, i)
  9039. ArraySetCell(g_extraitem_cost, g_extraitem_i, buffer[0])
  9040.  
  9041. // Replace team
  9042. buffer[0] = ArrayGetCell(g_extraitem2_team, i)
  9043. ArraySetCell(g_extraitem_team, g_extraitem_i, buffer[0])
  9044. }
  9045.  
  9046. // Increase registered items counter
  9047. g_extraitem_i++
  9048.  
  9049. // Return id under which we registered the item
  9050. return g_extraitem_i-1;
  9051. }
  9052.  
  9053. // Function: zp_register_extra_item (to be used within this plugin only)
  9054. native_register_extra_item2(const name[], cost, team)
  9055. {
  9056. // Add the item
  9057. ArrayPushString(g_extraitem_name, name)
  9058. ArrayPushCell(g_extraitem_cost, cost)
  9059. ArrayPushCell(g_extraitem_team, team)
  9060.  
  9061. // Set temporary new item flag
  9062. ArrayPushCell(g_extraitem_new, 1)
  9063.  
  9064. // Increase registered items counter
  9065. g_extraitem_i++
  9066. }
  9067.  
  9068. // Native: zp_register_zombie_class
  9069. public native_register_zombie_class(const name[], const info[], const model[], const clawmodel[], hp, speed, Float:gravity, Float:knockback)
  9070. {
  9071. // ZP disabled
  9072. if (!g_pluginenabled)
  9073. return -1;
  9074.  
  9075. // Arrays not yet initialized
  9076. if (!g_arrays_created)
  9077. return -1;
  9078.  
  9079. // Strings passed byref
  9080. param_convert(1)
  9081. param_convert(2)
  9082. param_convert(3)
  9083. param_convert(4)
  9084.  
  9085. // Add the class
  9086. ArrayPushString(g_zclass_name, name)
  9087. ArrayPushString(g_zclass_info, info)
  9088.  
  9089. // Using same zombie models for all classes?
  9090. if (g_same_models_for_all)
  9091. {
  9092. ArrayPushCell(g_zclass_modelsstart, 0)
  9093. ArrayPushCell(g_zclass_modelsend, ArraySize(g_zclass_playermodel))
  9094. }
  9095. else
  9096. {
  9097. ArrayPushCell(g_zclass_modelsstart, ArraySize(g_zclass_playermodel))
  9098. ArrayPushString(g_zclass_playermodel, model)
  9099. ArrayPushCell(g_zclass_modelsend, ArraySize(g_zclass_playermodel))
  9100. ArrayPushCell(g_zclass_modelindex, -1)
  9101. }
  9102.  
  9103. ArrayPushString(g_zclass_clawmodel, clawmodel)
  9104. ArrayPushCell(g_zclass_hp, hp)
  9105. ArrayPushCell(g_zclass_spd, speed)
  9106. ArrayPushCell(g_zclass_grav, gravity)
  9107. ArrayPushCell(g_zclass_kb, knockback)
  9108.  
  9109. // Set temporary new class flag
  9110. ArrayPushCell(g_zclass_new, 1)
  9111.  
  9112. // Override zombie classes data with our customizations
  9113. new i, k, buffer[32], Float:buffer2, nummodels_custom, nummodels_default, prec_mdl[100], size = ArraySize(g_zclass2_realname)
  9114. for (i = 0; i < size; i++)
  9115. {
  9116. ArrayGetString(g_zclass2_realname, i, buffer, charsmax(buffer))
  9117.  
  9118. // Check if this is the intended class to override
  9119. if (!equal(name, buffer))
  9120. continue;
  9121.  
  9122. // Remove new class flag
  9123. ArraySetCell(g_zclass_new, g_zclass_i, 0)
  9124.  
  9125. // Replace caption
  9126. ArrayGetString(g_zclass2_name, i, buffer, charsmax(buffer))
  9127. ArraySetString(g_zclass_name, g_zclass_i, buffer)
  9128.  
  9129. // Replace info
  9130. ArrayGetString(g_zclass2_info, i, buffer, charsmax(buffer))
  9131. ArraySetString(g_zclass_info, g_zclass_i, buffer)
  9132.  
  9133. // Replace models, unless using same models for all classes
  9134. if (!g_same_models_for_all)
  9135. {
  9136. nummodels_custom = ArrayGetCell(g_zclass2_modelsend, i) - ArrayGetCell(g_zclass2_modelsstart, i)
  9137. nummodels_default = ArrayGetCell(g_zclass_modelsend, g_zclass_i) - ArrayGetCell(g_zclass_modelsstart, g_zclass_i)
  9138.  
  9139. // Replace each player model and model index
  9140. for (k = 0; k < min(nummodels_custom, nummodels_default); k++)
  9141. {
  9142. ArrayGetString(g_zclass2_playermodel, ArrayGetCell(g_zclass2_modelsstart, i) + k, buffer, charsmax(buffer))
  9143. ArraySetString(g_zclass_playermodel, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k, buffer)
  9144.  
  9145. // Precache player model and replace its modelindex with the real one
  9146. formatex(prec_mdl, charsmax(prec_mdl), "models/player/%s/%s.mdl", buffer, buffer)
  9147. ArraySetCell(g_zclass_modelindex, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k, engfunc(EngFunc_PrecacheModel, prec_mdl))
  9148. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, prec_mdl)
  9149. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, prec_mdl)
  9150. }
  9151.  
  9152. // We have more custom models than what we can accommodate,
  9153. // Let's make some space...
  9154. if (nummodels_custom > nummodels_default)
  9155. {
  9156. for (k = nummodels_default; k < nummodels_custom; k++)
  9157. {
  9158. ArrayGetString(g_zclass2_playermodel, ArrayGetCell(g_zclass2_modelsstart, i) + k, buffer, charsmax(buffer))
  9159. ArrayInsertStringAfter(g_zclass_playermodel, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k - 1, buffer)
  9160.  
  9161. // Precache player model and retrieve its modelindex
  9162. formatex(prec_mdl, charsmax(prec_mdl), "models/player/%s/%s.mdl", buffer, buffer)
  9163. ArrayInsertCellAfter(g_zclass_modelindex, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k - 1, engfunc(EngFunc_PrecacheModel, prec_mdl))
  9164. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, prec_mdl)
  9165. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, prec_mdl)
  9166. }
  9167.  
  9168. // Fix models end index for this class
  9169. ArraySetCell(g_zclass_modelsend, g_zclass_i, ArrayGetCell(g_zclass_modelsend, g_zclass_i) + (nummodels_custom - nummodels_default))
  9170. }
  9171.  
  9172. /* --- Not needed since classes can't have more than 1 default model for now ---
  9173. // We have less custom models than what this class has by default,
  9174. // Get rid of those extra entries...
  9175. if (nummodels_custom < nummodels_default)
  9176. {
  9177. for (k = nummodels_custom; k < nummodels_default; k++)
  9178. {
  9179. ArrayDeleteItem(g_zclass_playermodel, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + nummodels_custom)
  9180. }
  9181.  
  9182. // Fix models end index for this class
  9183. ArraySetCell(g_zclass_modelsend, g_zclass_i, ArrayGetCell(g_zclass_modelsend, g_zclass_i) - (nummodels_default - nummodels_custom))
  9184. }
  9185. */
  9186. }
  9187.  
  9188. // Replace clawmodel
  9189. ArrayGetString(g_zclass2_clawmodel, i, buffer, charsmax(buffer))
  9190. ArraySetString(g_zclass_clawmodel, g_zclass_i, buffer)
  9191.  
  9192. // Precache clawmodel
  9193. formatex(prec_mdl, charsmax(prec_mdl), "models/zombie_plague/%s", buffer)
  9194. engfunc(EngFunc_PrecacheModel, prec_mdl)
  9195.  
  9196. // Replace health
  9197. buffer[0] = ArrayGetCell(g_zclass2_hp, i)
  9198. ArraySetCell(g_zclass_hp, g_zclass_i, buffer[0])
  9199.  
  9200. // Replace speed
  9201. buffer[0] = ArrayGetCell(g_zclass2_spd, i)
  9202. ArraySetCell(g_zclass_spd, g_zclass_i, buffer[0])
  9203.  
  9204. // Replace gravity
  9205. buffer2 = Float:ArrayGetCell(g_zclass2_grav, i)
  9206. ArraySetCell(g_zclass_grav, g_zclass_i, buffer2)
  9207.  
  9208. // Replace knockback
  9209. buffer2 = Float:ArrayGetCell(g_zclass2_kb, i)
  9210. ArraySetCell(g_zclass_kb, g_zclass_i, buffer2)
  9211. }
  9212.  
  9213. // If class was not overriden with customization data
  9214. if (ArrayGetCell(g_zclass_new, g_zclass_i))
  9215. {
  9216. // If not using same models for all classes
  9217. if (!g_same_models_for_all)
  9218. {
  9219. // Precache default class model and replace modelindex with the real one
  9220. formatex(prec_mdl, charsmax(prec_mdl), "models/player/%s/%s.mdl", model, model)
  9221. ArraySetCell(g_zclass_modelindex, ArrayGetCell(g_zclass_modelsstart, g_zclass_i), engfunc(EngFunc_PrecacheModel, prec_mdl))
  9222. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, prec_mdl)
  9223. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, prec_mdl)
  9224. }
  9225.  
  9226. // Precache default clawmodel
  9227. formatex(prec_mdl, charsmax(prec_mdl), "models/zombie_plague/%s", clawmodel)
  9228. engfunc(EngFunc_PrecacheModel, prec_mdl)
  9229. }
  9230.  
  9231. // Increase registered classes counter
  9232. g_zclass_i++
  9233.  
  9234. // Return id under which we registered the class
  9235. return g_zclass_i-1;
  9236. }
  9237.  
  9238. // Native: zp_get_extra_item_id
  9239. public native_get_extra_item_id(const name[])
  9240. {
  9241. // ZP disabled
  9242. if (!g_pluginenabled)
  9243. return -1;
  9244.  
  9245. // Strings passed byref
  9246. param_convert(1)
  9247.  
  9248. // Loop through every item
  9249. static i, item_name[32]
  9250. for (i = 0; i < g_extraitem_i; i++)
  9251. {
  9252. ArrayGetString(g_extraitem_name, i, item_name, charsmax(item_name))
  9253.  
  9254. // Check if this is the item to retrieve
  9255. if (equali(name, item_name))
  9256. return i;
  9257. }
  9258.  
  9259. return -1;
  9260. }
  9261.  
  9262. // Native: zp_get_zombie_class_id
  9263. public native_get_zombie_class_id(const name[])
  9264. {
  9265. // ZP disabled
  9266. if (!g_pluginenabled)
  9267. return -1;
  9268.  
  9269. // Strings passed byref
  9270. param_convert(1)
  9271.  
  9272. // Loop through every class
  9273. static i, class_name[32]
  9274. for (i = 0; i < g_zclass_i; i++)
  9275. {
  9276. ArrayGetString(g_zclass_name, i, class_name, charsmax(class_name))
  9277.  
  9278. // Check if this is the class to retrieve
  9279. if (equali(name, class_name))
  9280. return i;
  9281. }
  9282.  
  9283. return -1;
  9284. }
  9285.  
  9286. /*================================================================================
  9287. [Custom Messages]
  9288. =================================================================================*/
  9289.  
  9290. // Custom Night Vision
  9291. public set_user_nvision(taskid)
  9292. {
  9293. // Get player's origin
  9294. static origin[3]
  9295. get_user_origin(ID_NVISION, origin)
  9296.  
  9297. // Nightvision message
  9298. message_begin(MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, _, ID_NVISION)
  9299. write_byte(TE_DLIGHT) // TE id
  9300. write_coord(origin[0]) // x
  9301. write_coord(origin[1]) // y
  9302. write_coord(origin[2]) // z
  9303. write_byte(get_pcvar_num(cvar_nvgsize)) // radius
  9304.  
  9305. // Nemesis / Madness / Spectator in nemesis round
  9306. if (g_nemesis[ID_NVISION] || (g_zombie[ID_NVISION] && g_nodamage[ID_NVISION]) || (!g_isalive[ID_NVISION] && g_nemround))
  9307. {
  9308. write_byte(get_pcvar_num(cvar_nemnvgcolor[0])) // r
  9309. write_byte(get_pcvar_num(cvar_nemnvgcolor[1])) // g
  9310. write_byte(get_pcvar_num(cvar_nemnvgcolor[2])) // b
  9311. }
  9312. // Human / Spectator in normal round
  9313. else if (!g_zombie[ID_NVISION] || !g_isalive[ID_NVISION])
  9314. {
  9315. write_byte(get_pcvar_num(cvar_humnvgcolor[0])) // r
  9316. write_byte(get_pcvar_num(cvar_humnvgcolor[1])) // g
  9317. write_byte(get_pcvar_num(cvar_humnvgcolor[2])) // b
  9318. }
  9319. // Zombie
  9320. else
  9321. {
  9322. write_byte(get_pcvar_num(cvar_nvgcolor[0])) // r
  9323. write_byte(get_pcvar_num(cvar_nvgcolor[1])) // g
  9324. write_byte(get_pcvar_num(cvar_nvgcolor[2])) // b
  9325. }
  9326.  
  9327. write_byte(2) // life
  9328. write_byte(0) // decay rate
  9329. message_end()
  9330. }
  9331.  
  9332. // Game Nightvision
  9333. set_user_gnvision(id, toggle)
  9334. {
  9335. // Toggle NVG message
  9336. message_begin(MSG_ONE, g_msgNVGToggle, _, id)
  9337. write_byte(toggle) // toggle
  9338. message_end()
  9339. }
  9340.  
  9341. // Custom Flashlight
  9342. public set_user_flashlight(taskid)
  9343. {
  9344. // Get player and aiming origins
  9345. static Float:originF[3], Float:destoriginF[3]
  9346. pev(ID_FLASH, pev_origin, originF)
  9347. fm_get_aim_origin(ID_FLASH, destoriginF)
  9348.  
  9349. // Max distance check
  9350. if (get_distance_f(originF, destoriginF) > get_pcvar_float(cvar_flashdist))
  9351. return;
  9352.  
  9353. // Send to all players?
  9354. if (get_pcvar_num(cvar_flashshowall))
  9355. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, destoriginF, 0)
  9356. else
  9357. message_begin(MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, _, ID_FLASH)
  9358.  
  9359. // Flashlight
  9360. write_byte(TE_DLIGHT) // TE id
  9361. engfunc(EngFunc_WriteCoord, destoriginF[0]) // x
  9362. engfunc(EngFunc_WriteCoord, destoriginF[1]) // y
  9363. engfunc(EngFunc_WriteCoord, destoriginF[2]) // z
  9364. write_byte(get_pcvar_num(cvar_flashsize)) // radius
  9365. write_byte(get_pcvar_num(cvar_flashcolor[0])) // r
  9366. write_byte(get_pcvar_num(cvar_flashcolor[1])) // g
  9367. write_byte(get_pcvar_num(cvar_flashcolor[2])) // b
  9368. write_byte(3) // life
  9369. write_byte(0) // decay rate
  9370. message_end()
  9371. }
  9372.  
  9373. // Infection special effects
  9374. infection_effects(id)
  9375. {
  9376. // Screen fade? (unless frozen)
  9377. if (!g_frozen[id] && get_pcvar_num(cvar_infectionscreenfade))
  9378. {
  9379. message_begin(MSG_ONE_UNRELIABLE, g_msgScreenFade, _, id)
  9380. write_short(UNIT_SECOND) // duration
  9381. write_short(0) // hold time
  9382. write_short(FFADE_IN) // fade type
  9383. if (g_nemesis[id])
  9384. {
  9385. write_byte(get_pcvar_num(cvar_nemnvgcolor[0])) // r
  9386. write_byte(get_pcvar_num(cvar_nemnvgcolor[1])) // g
  9387. write_byte(get_pcvar_num(cvar_nemnvgcolor[2])) // b
  9388. }
  9389. else
  9390. {
  9391. write_byte(get_pcvar_num(cvar_nvgcolor[0])) // r
  9392. write_byte(get_pcvar_num(cvar_nvgcolor[1])) // g
  9393. write_byte(get_pcvar_num(cvar_nvgcolor[2])) // b
  9394. }
  9395. write_byte (255) // alpha
  9396. message_end()
  9397. }
  9398.  
  9399. // Screen shake?
  9400. if (get_pcvar_num(cvar_infectionscreenshake))
  9401. {
  9402. message_begin(MSG_ONE_UNRELIABLE, g_msgScreenShake, _, id)
  9403. write_short(UNIT_SECOND*4) // amplitude
  9404. write_short(UNIT_SECOND*2) // duration
  9405. write_short(UNIT_SECOND*10) // frequency
  9406. message_end()
  9407. }
  9408.  
  9409. // Infection icon?
  9410. if (get_pcvar_num(cvar_hudicons))
  9411. {
  9412. message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, _, id)
  9413. write_byte(0) // damage save
  9414. write_byte(0) // damage take
  9415. write_long(DMG_NERVEGAS) // damage type - DMG_RADIATION
  9416. write_coord(0) // x
  9417. write_coord(0) // y
  9418. write_coord(0) // z
  9419. message_end()
  9420. }
  9421.  
  9422. // Get player's origin
  9423. static origin[3]
  9424. get_user_origin(id, origin)
  9425.  
  9426. // Tracers?
  9427. if (get_pcvar_num(cvar_infectiontracers))
  9428. {
  9429. message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
  9430. write_byte(TE_IMPLOSION) // TE id
  9431. write_coord(origin[0]) // x
  9432. write_coord(origin[1]) // y
  9433. write_coord(origin[2]) // z
  9434. write_byte(128) // radius
  9435. write_byte(20) // count
  9436. write_byte(3) // duration
  9437. message_end()
  9438. }
  9439.  
  9440. // Particle burst?
  9441. if (get_pcvar_num(cvar_infectionparticles))
  9442. {
  9443. message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
  9444. write_byte(TE_PARTICLEBURST) // TE id
  9445. write_coord(origin[0]) // x
  9446. write_coord(origin[1]) // y
  9447. write_coord(origin[2]) // z
  9448. write_short(50) // radius
  9449. write_byte(70) // color
  9450. write_byte(3) // duration (will be randomized a bit)
  9451. message_end()
  9452. }
  9453.  
  9454. // Light sparkle?
  9455. if (get_pcvar_num(cvar_infectionsparkle))
  9456. {
  9457. message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
  9458. write_byte(TE_DLIGHT) // TE id
  9459. write_coord(origin[0]) // x
  9460. write_coord(origin[1]) // y
  9461. write_coord(origin[2]) // z
  9462. write_byte(20) // radius
  9463. write_byte(get_pcvar_num(cvar_nvgcolor[0])) // r
  9464. write_byte(get_pcvar_num(cvar_nvgcolor[1])) // g
  9465. write_byte(get_pcvar_num(cvar_nvgcolor[2])) // b
  9466. write_byte(2) // life
  9467. write_byte(0) // decay rate
  9468. message_end()
  9469. }
  9470. }
  9471.  
  9472. // Nemesis/madness aura task
  9473. public zombie_aura(taskid)
  9474. {
  9475. // Not nemesis, not in zombie madness
  9476. if (!g_nemesis[ID_AURA] && !g_nodamage[ID_AURA])
  9477. {
  9478. // Task not needed anymore
  9479. remove_task(taskid);
  9480. return;
  9481. }
  9482.  
  9483. // Get player's origin
  9484. static origin[3]
  9485. get_user_origin(ID_AURA, origin)
  9486.  
  9487. // Colored Aura
  9488. message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
  9489. write_byte(TE_DLIGHT) // TE id
  9490. write_coord(origin[0]) // x
  9491. write_coord(origin[1]) // y
  9492. write_coord(origin[2]) // z
  9493. write_byte(20) // radius
  9494. write_byte(get_pcvar_num(cvar_nemnvgcolor[0])) // r
  9495. write_byte(get_pcvar_num(cvar_nemnvgcolor[1])) // g
  9496. write_byte(get_pcvar_num(cvar_nemnvgcolor[2])) // b
  9497. write_byte(2) // life
  9498. write_byte(0) // decay rate
  9499. message_end()
  9500. }
  9501.  
  9502. // Make zombies leave footsteps and bloodstains on the floor
  9503. public make_blood(taskid)
  9504. {
  9505. // Only bleed when moving on ground
  9506. if (!(pev(ID_BLOOD, pev_flags) & FL_ONGROUND) || fm_get_speed(ID_BLOOD) < 80)
  9507. return;
  9508.  
  9509. // Get user origin
  9510. static Float:originF[3]
  9511. pev(ID_BLOOD, pev_origin, originF)
  9512.  
  9513. // If ducking set a little lower
  9514. if (pev(ID_BLOOD, pev_bInDuck))
  9515. originF[2] -= 18.0
  9516. else
  9517. originF[2] -= 36.0
  9518.  
  9519. // Send the decal message
  9520. engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, originF, 0)
  9521. write_byte(TE_WORLDDECAL) // TE id
  9522. engfunc(EngFunc_WriteCoord, originF[0]) // x
  9523. engfunc(EngFunc_WriteCoord, originF[1]) // y
  9524. engfunc(EngFunc_WriteCoord, originF[2]) // z
  9525. write_byte(ArrayGetCell(zombie_decals, random_num(0, ArraySize(zombie_decals) - 1)) + (g_czero * 12)) // random decal number (offsets +12 for CZ)
  9526. message_end()
  9527. }
  9528.  
  9529. // Flare Lighting Effects
  9530. flare_lighting(entity, duration)
  9531. {
  9532. // Get origin and color
  9533. static Float:originF[3], color[3]
  9534. pev(entity, pev_origin, originF)
  9535. pev(entity, PEV_FLARE_COLOR, color)
  9536.  
  9537. // Lighting
  9538. engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, originF, 0)
  9539. write_byte(TE_DLIGHT) // TE id
  9540. engfunc(EngFunc_WriteCoord, originF[0]) // x
  9541. engfunc(EngFunc_WriteCoord, originF[1]) // y
  9542. engfunc(EngFunc_WriteCoord, originF[2]) // z
  9543. write_byte(get_pcvar_num(cvar_flaresize)) // radius
  9544. write_byte(color[0]) // r
  9545. write_byte(color[1]) // g
  9546. write_byte(color[2]) // b
  9547. write_byte(51) //life
  9548. write_byte((duration < 2) ? 3 : 0) //decay rate
  9549. message_end()
  9550.  
  9551. // Sparks
  9552. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  9553. write_byte(TE_SPARKS) // TE id
  9554. engfunc(EngFunc_WriteCoord, originF[0]) // x
  9555. engfunc(EngFunc_WriteCoord, originF[1]) // y
  9556. engfunc(EngFunc_WriteCoord, originF[2]) // z
  9557. message_end()
  9558. }
  9559.  
  9560. // Burning Flames
  9561. public burning_flame(taskid)
  9562. {
  9563. // Get player origin and flags
  9564. static origin[3], flags
  9565. get_user_origin(ID_BURN, origin)
  9566. flags = pev(ID_BURN, pev_flags)
  9567.  
  9568. // Madness mode - in water - burning stopped
  9569. if (g_nodamage[ID_BURN] || (flags & FL_INWATER) || g_burning_duration[ID_BURN] < 1)
  9570. {
  9571. // Smoke sprite
  9572. message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
  9573. write_byte(TE_SMOKE) // TE id
  9574. write_coord(origin[0]) // x
  9575. write_coord(origin[1]) // y
  9576. write_coord(origin[2]-50) // z
  9577. write_short(g_smokeSpr) // sprite
  9578. write_byte(random_num(15, 20)) // scale
  9579. write_byte(random_num(10, 20)) // framerate
  9580. message_end()
  9581.  
  9582. // Task not needed anymore
  9583. remove_task(taskid);
  9584. return;
  9585. }
  9586.  
  9587. // Randomly play burning zombie scream sounds (not for nemesis)
  9588. if (!g_nemesis[ID_BURN] && !random_num(0, 20))
  9589. {
  9590. static sound[64]
  9591. ArrayGetString(grenade_fire_player, random_num(0, ArraySize(grenade_fire_player) - 1), sound, charsmax(sound))
  9592. emit_sound(ID_BURN, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  9593. }
  9594.  
  9595. // Fire slow down, unless nemesis
  9596. if (!g_nemesis[ID_BURN] && (flags & FL_ONGROUND) && get_pcvar_float(cvar_fireslowdown) > 0.0)
  9597. {
  9598. static Float:velocity[3]
  9599. pev(ID_BURN, pev_velocity, velocity)
  9600. xs_vec_mul_scalar(velocity, get_pcvar_float(cvar_fireslowdown), velocity)
  9601. set_pev(ID_BURN, pev_velocity, velocity)
  9602. }
  9603.  
  9604. // Get player's health
  9605. static health
  9606. health = pev(ID_BURN, pev_health)
  9607.  
  9608. // Take damage from the fire
  9609. if (health - floatround(get_pcvar_float(cvar_firedamage), floatround_ceil) > 0)
  9610. fm_set_user_health(ID_BURN, health - floatround(get_pcvar_float(cvar_firedamage), floatround_ceil))
  9611.  
  9612. // Flame sprite
  9613. message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
  9614. write_byte(TE_SPRITE) // TE id
  9615. write_coord(origin[0]+random_num(-5, 5)) // x
  9616. write_coord(origin[1]+random_num(-5, 5)) // y
  9617. write_coord(origin[2]+random_num(-10, 10)) // z
  9618. write_short(g_flameSpr) // sprite
  9619. write_byte(random_num(5, 10)) // scale
  9620. write_byte(200) // brightness
  9621. message_end()
  9622.  
  9623. // Decrease burning duration counter
  9624. g_burning_duration[ID_BURN]--
  9625. }
  9626.  
  9627. // Infection Bomb: Green Blast
  9628. create_blast(const Float:originF[3])
  9629. {
  9630. // Smallest ring
  9631. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  9632. write_byte(TE_BEAMCYLINDER) // TE id
  9633. engfunc(EngFunc_WriteCoord, originF[0]) // x
  9634. engfunc(EngFunc_WriteCoord, originF[1]) // y
  9635. engfunc(EngFunc_WriteCoord, originF[2]) // z
  9636. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  9637. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  9638. engfunc(EngFunc_WriteCoord, originF[2]+385.0) // z axis
  9639. write_short(g_exploSpr) // sprite
  9640. write_byte(0) // startframe
  9641. write_byte(0) // framerate
  9642. write_byte(4) // life
  9643. write_byte(60) // width
  9644. write_byte(0) // noise
  9645. write_byte(0) // red
  9646. write_byte(200) // green
  9647. write_byte(0) // blue
  9648. write_byte(200) // brightness
  9649. write_byte(0) // speed
  9650. message_end()
  9651.  
  9652. // Medium ring
  9653. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  9654. write_byte(TE_BEAMCYLINDER) // TE id
  9655. engfunc(EngFunc_WriteCoord, originF[0]) // x
  9656. engfunc(EngFunc_WriteCoord, originF[1]) // y
  9657. engfunc(EngFunc_WriteCoord, originF[2]) // z
  9658. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  9659. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  9660. engfunc(EngFunc_WriteCoord, originF[2]+470.0) // z axis
  9661. write_short(g_exploSpr) // sprite
  9662. write_byte(0) // startframe
  9663. write_byte(0) // framerate
  9664. write_byte(4) // life
  9665. write_byte(60) // width
  9666. write_byte(0) // noise
  9667. write_byte(0) // red
  9668. write_byte(200) // green
  9669. write_byte(0) // blue
  9670. write_byte(200) // brightness
  9671. write_byte(0) // speed
  9672. message_end()
  9673.  
  9674. // Largest ring
  9675. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  9676. write_byte(TE_BEAMCYLINDER) // TE id
  9677. engfunc(EngFunc_WriteCoord, originF[0]) // x
  9678. engfunc(EngFunc_WriteCoord, originF[1]) // y
  9679. engfunc(EngFunc_WriteCoord, originF[2]) // z
  9680. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  9681. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  9682. engfunc(EngFunc_WriteCoord, originF[2]+555.0) // z axis
  9683. write_short(g_exploSpr) // sprite
  9684. write_byte(0) // startframe
  9685. write_byte(0) // framerate
  9686. write_byte(4) // life
  9687. write_byte(60) // width
  9688. write_byte(0) // noise
  9689. write_byte(0) // red
  9690. write_byte(200) // green
  9691. write_byte(0) // blue
  9692. write_byte(200) // brightness
  9693. write_byte(0) // speed
  9694. message_end()
  9695. }
  9696.  
  9697. // Fire Grenade: Fire Blast
  9698. create_blast2(const Float:originF[3])
  9699. {
  9700. // Smallest ring
  9701. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  9702. write_byte(TE_BEAMCYLINDER) // TE id
  9703. engfunc(EngFunc_WriteCoord, originF[0]) // x
  9704. engfunc(EngFunc_WriteCoord, originF[1]) // y
  9705. engfunc(EngFunc_WriteCoord, originF[2]) // z
  9706. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  9707. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  9708. engfunc(EngFunc_WriteCoord, originF[2]+385.0) // z axis
  9709. write_short(g_exploSpr) // sprite
  9710. write_byte(0) // startframe
  9711. write_byte(0) // framerate
  9712. write_byte(4) // life
  9713. write_byte(60) // width
  9714. write_byte(0) // noise
  9715. write_byte(200) // red
  9716. write_byte(100) // green
  9717. write_byte(0) // blue
  9718. write_byte(200) // brightness
  9719. write_byte(0) // speed
  9720. message_end()
  9721.  
  9722. // Medium ring
  9723. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  9724. write_byte(TE_BEAMCYLINDER) // TE id
  9725. engfunc(EngFunc_WriteCoord, originF[0]) // x
  9726. engfunc(EngFunc_WriteCoord, originF[1]) // y
  9727. engfunc(EngFunc_WriteCoord, originF[2]) // z
  9728. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  9729. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  9730. engfunc(EngFunc_WriteCoord, originF[2]+470.0) // z axis
  9731. write_short(g_exploSpr) // sprite
  9732. write_byte(0) // startframe
  9733. write_byte(0) // framerate
  9734. write_byte(4) // life
  9735. write_byte(60) // width
  9736. write_byte(0) // noise
  9737. write_byte(200) // red
  9738. write_byte(50) // green
  9739. write_byte(0) // blue
  9740. write_byte(200) // brightness
  9741. write_byte(0) // speed
  9742. message_end()
  9743.  
  9744. // Largest ring
  9745. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  9746. write_byte(TE_BEAMCYLINDER) // TE id
  9747. engfunc(EngFunc_WriteCoord, originF[0]) // x
  9748. engfunc(EngFunc_WriteCoord, originF[1]) // y
  9749. engfunc(EngFunc_WriteCoord, originF[2]) // z
  9750. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  9751. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  9752. engfunc(EngFunc_WriteCoord, originF[2]+555.0) // z axis
  9753. write_short(g_exploSpr) // sprite
  9754. write_byte(0) // startframe
  9755. write_byte(0) // framerate
  9756. write_byte(4) // life
  9757. write_byte(60) // width
  9758. write_byte(0) // noise
  9759. write_byte(200) // red
  9760. write_byte(0) // green
  9761. write_byte(0) // blue
  9762. write_byte(200) // brightness
  9763. write_byte(0) // speed
  9764. message_end()
  9765. }
  9766.  
  9767. // Frost Grenade: Freeze Blast
  9768. create_blast3(const Float:originF[3])
  9769. {
  9770. // Smallest ring
  9771. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  9772. write_byte(TE_BEAMCYLINDER) // TE id
  9773. engfunc(EngFunc_WriteCoord, originF[0]) // x
  9774. engfunc(EngFunc_WriteCoord, originF[1]) // y
  9775. engfunc(EngFunc_WriteCoord, originF[2]) // z
  9776. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  9777. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  9778. engfunc(EngFunc_WriteCoord, originF[2]+385.0) // z axis
  9779. write_short(g_exploSpr) // sprite
  9780. write_byte(0) // startframe
  9781. write_byte(0) // framerate
  9782. write_byte(4) // life
  9783. write_byte(60) // width
  9784. write_byte(0) // noise
  9785. write_byte(0) // red
  9786. write_byte(100) // green
  9787. write_byte(200) // blue
  9788. write_byte(200) // brightness
  9789. write_byte(0) // speed
  9790. message_end()
  9791.  
  9792. // Medium ring
  9793. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  9794. write_byte(TE_BEAMCYLINDER) // TE id
  9795. engfunc(EngFunc_WriteCoord, originF[0]) // x
  9796. engfunc(EngFunc_WriteCoord, originF[1]) // y
  9797. engfunc(EngFunc_WriteCoord, originF[2]) // z
  9798. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  9799. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  9800. engfunc(EngFunc_WriteCoord, originF[2]+470.0) // z axis
  9801. write_short(g_exploSpr) // sprite
  9802. write_byte(0) // startframe
  9803. write_byte(0) // framerate
  9804. write_byte(4) // life
  9805. write_byte(60) // width
  9806. write_byte(0) // noise
  9807. write_byte(0) // red
  9808. write_byte(100) // green
  9809. write_byte(200) // blue
  9810. write_byte(200) // brightness
  9811. write_byte(0) // speed
  9812. message_end()
  9813.  
  9814. // Largest ring
  9815. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  9816. write_byte(TE_BEAMCYLINDER) // TE id
  9817. engfunc(EngFunc_WriteCoord, originF[0]) // x
  9818. engfunc(EngFunc_WriteCoord, originF[1]) // y
  9819. engfunc(EngFunc_WriteCoord, originF[2]) // z
  9820. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  9821. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  9822. engfunc(EngFunc_WriteCoord, originF[2]+555.0) // z axis
  9823. write_short(g_exploSpr) // sprite
  9824. write_byte(0) // startframe
  9825. write_byte(0) // framerate
  9826. write_byte(4) // life
  9827. write_byte(60) // width
  9828. write_byte(0) // noise
  9829. write_byte(0) // red
  9830. write_byte(100) // green
  9831. write_byte(200) // blue
  9832. write_byte(200) // brightness
  9833. write_byte(0) // speed
  9834. message_end()
  9835. }
  9836.  
  9837. // Fix Dead Attrib on scoreboard
  9838. FixDeadAttrib(id)
  9839. {
  9840. message_begin(MSG_BROADCAST, g_msgScoreAttrib)
  9841. write_byte(id) // id
  9842. write_byte(0) // attrib
  9843. message_end()
  9844. }
  9845.  
  9846. // Send Death Message for infections
  9847. SendDeathMsg(attacker, victim)
  9848. {
  9849. message_begin(MSG_BROADCAST, g_msgDeathMsg)
  9850. write_byte(attacker) // killer
  9851. write_byte(victim) // victim
  9852. write_byte(1) // headshot flag
  9853. write_string("infection") // killer's weapon
  9854. message_end()
  9855. }
  9856.  
  9857. // Update Player Frags and Deaths
  9858. UpdateFrags(attacker, victim, frags, deaths, scoreboard)
  9859. {
  9860. // Set attacker frags
  9861. set_pev(attacker, pev_frags, float(pev(attacker, pev_frags) + frags))
  9862.  
  9863. // Set victim deaths
  9864. fm_cs_set_user_deaths(victim, cs_get_user_deaths(victim) + deaths)
  9865.  
  9866. // Update scoreboard with attacker and victim info
  9867. if (scoreboard)
  9868. {
  9869. message_begin(MSG_BROADCAST, g_msgScoreInfo)
  9870. write_byte(attacker) // id
  9871. write_short(pev(attacker, pev_frags)) // frags
  9872. write_short(cs_get_user_deaths(attacker)) // deaths
  9873. write_short(0) // class?
  9874. write_short(fm_cs_get_user_team(attacker)) // team
  9875. message_end()
  9876.  
  9877. message_begin(MSG_BROADCAST, g_msgScoreInfo)
  9878. write_byte(victim) // id
  9879. write_short(pev(victim, pev_frags)) // frags
  9880. write_short(cs_get_user_deaths(victim)) // deaths
  9881. write_short(0) // class?
  9882. write_short(fm_cs_get_user_team(victim)) // team
  9883. message_end()
  9884. }
  9885. }
  9886.  
  9887. // Remove Player Frags (when Nemesis/Survivor ignore_frags cvar is enabled)
  9888. RemoveFrags(attacker, victim)
  9889. {
  9890. // Remove attacker frags
  9891. set_pev(attacker, pev_frags, float(pev(attacker, pev_frags) - 1))
  9892.  
  9893. // Remove victim deaths
  9894. fm_cs_set_user_deaths(victim, cs_get_user_deaths(victim) - 1)
  9895. }
  9896.  
  9897. // Plays a sound on clients
  9898. PlaySound(const sound[])
  9899. {
  9900. client_cmd(0, "spk ^"%s^"", sound)
  9901. }
  9902.  
  9903. // Prints a colored message to target (use 0 for everyone), supports ML formatting.
  9904. // Note: I still need to make something like gungame's LANG_PLAYER_C to avoid unintended
  9905. // argument replacement when a function passes -1 (it will be considered a LANG_PLAYER)
  9906. zp_colored_print(target, const message[], any:...)
  9907. {
  9908. static buffer[512], i, argscount
  9909. argscount = numargs()
  9910.  
  9911. // Send to everyone
  9912. if (!target)
  9913. {
  9914. static player
  9915. for (player = 1; player <= g_maxplayers; player++)
  9916. {
  9917. // Not connected
  9918. if (!g_isconnected[player])
  9919. continue;
  9920.  
  9921. // Remember changed arguments
  9922. static changed[5], changedcount // [5] = max LANG_PLAYER occurencies
  9923. changedcount = 0
  9924.  
  9925. // Replace LANG_PLAYER with player id
  9926. for (i = 2; i < argscount; i++)
  9927. {
  9928. if (getarg(i) == LANG_PLAYER)
  9929. {
  9930. setarg(i, 0, player)
  9931. changed[changedcount] = i
  9932. changedcount++
  9933. }
  9934. }
  9935.  
  9936. // Format message for player
  9937. vformat(buffer, charsmax(buffer), message, 3)
  9938.  
  9939. // Send it
  9940. message_begin(MSG_ONE_UNRELIABLE, g_msgSayText, _, player)
  9941. write_byte(player)
  9942. write_string(buffer)
  9943. message_end()
  9944.  
  9945. // Replace back player id's with LANG_PLAYER
  9946. for (i = 0; i < changedcount; i++)
  9947. setarg(changed[i], 0, LANG_PLAYER)
  9948. }
  9949. }
  9950. // Send to specific target
  9951. else
  9952. {
  9953. /*
  9954. // Not needed since you should set the ML argument
  9955. // to the player's id for a targeted print message
  9956.  
  9957. // Replace LANG_PLAYER with player id
  9958. for (i = 2; i < argscount; i++)
  9959. {
  9960. if (getarg(i) == LANG_PLAYER)
  9961. setarg(i, 0, target)
  9962. }
  9963. */
  9964.  
  9965. // Format message for player
  9966. vformat(buffer, charsmax(buffer), message, 3)
  9967.  
  9968. // Send it
  9969. message_begin(MSG_ONE, g_msgSayText, _, target)
  9970. write_byte(target)
  9971. write_string(buffer)
  9972. message_end()
  9973. }
  9974. }
  9975.  
  9976. /*================================================================================
  9977. [Stocks]
  9978. =================================================================================*/
  9979.  
  9980. // Set an entity's key value (from fakemeta_util)
  9981. stock fm_set_kvd(entity, const key[], const value[], const classname[])
  9982. {
  9983. set_kvd(0, KV_ClassName, classname)
  9984. set_kvd(0, KV_KeyName, key)
  9985. set_kvd(0, KV_Value, value)
  9986. set_kvd(0, KV_fHandled, 0)
  9987.  
  9988. dllfunc(DLLFunc_KeyValue, entity, 0)
  9989. }
  9990.  
  9991. // Set entity's rendering type (from fakemeta_util)
  9992. stock fm_set_rendering(entity, fx = kRenderFxNone, r = 255, g = 255, b = 255, render = kRenderNormal, amount = 16)
  9993. {
  9994. static Float:color[3]
  9995. color[0] = float(r)
  9996. color[1] = float(g)
  9997. color[2] = float(b)
  9998.  
  9999. set_pev(entity, pev_renderfx, fx)
  10000. set_pev(entity, pev_rendercolor, color)
  10001. set_pev(entity, pev_rendermode, render)
  10002. set_pev(entity, pev_renderamt, float(amount))
  10003. }
  10004.  
  10005. // Get entity's speed (from fakemeta_util)
  10006. stock fm_get_speed(entity)
  10007. {
  10008. static Float:velocity[3]
  10009. pev(entity, pev_velocity, velocity)
  10010.  
  10011. return floatround(vector_length(velocity));
  10012. }
  10013.  
  10014. // Get entity's aim origins (from fakemeta_util)
  10015. stock fm_get_aim_origin(id, Float:origin[3])
  10016. {
  10017. static Float:origin1F[3], Float:origin2F[3]
  10018. pev(id, pev_origin, origin1F)
  10019. pev(id, pev_view_ofs, origin2F)
  10020. xs_vec_add(origin1F, origin2F, origin1F)
  10021.  
  10022. pev(id, pev_v_angle, origin2F);
  10023. engfunc(EngFunc_MakeVectors, origin2F)
  10024. global_get(glb_v_forward, origin2F)
  10025. xs_vec_mul_scalar(origin2F, 9999.0, origin2F)
  10026. xs_vec_add(origin1F, origin2F, origin2F)
  10027.  
  10028. engfunc(EngFunc_TraceLine, origin1F, origin2F, 0, id, 0)
  10029. get_tr2(0, TR_vecEndPos, origin)
  10030. }
  10031.  
  10032. // Find entity by its owner (from fakemeta_util)
  10033. stock fm_find_ent_by_owner(entity, const classname[], owner)
  10034. {
  10035. while ((entity = engfunc(EngFunc_FindEntityByString, entity, "classname", classname)) && pev(entity, pev_owner) != owner) { /* keep looping */ }
  10036. return entity;
  10037. }
  10038.  
  10039. // Set player's health (from fakemeta_util)
  10040. stock fm_set_user_health(id, health)
  10041. {
  10042. (health > 0) ? set_pev(id, pev_health, float(health)) : dllfunc(DLLFunc_ClientKill, id);
  10043. }
  10044.  
  10045. // Give an item to a player (from fakemeta_util)
  10046. stock fm_give_item(id, const item[])
  10047. {
  10048. static ent
  10049. ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, item))
  10050. if (!pev_valid(ent)) return;
  10051.  
  10052. static Float:originF[3]
  10053. pev(id, pev_origin, originF)
  10054. set_pev(ent, pev_origin, originF)
  10055. set_pev(ent, pev_spawnflags, pev(ent, pev_spawnflags) | SF_NORESPAWN)
  10056. dllfunc(DLLFunc_Spawn, ent)
  10057.  
  10058. static save
  10059. save = pev(ent, pev_solid)
  10060. dllfunc(DLLFunc_Touch, ent, id)
  10061. if (pev(ent, pev_solid) != save)
  10062. return;
  10063.  
  10064. engfunc(EngFunc_RemoveEntity, ent)
  10065. }
  10066.  
  10067. // Strip user weapons (from fakemeta_util)
  10068. stock fm_strip_user_weapons(id)
  10069. {
  10070. static ent
  10071. ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "player_weaponstrip"))
  10072. if (!pev_valid(ent)) return;
  10073.  
  10074. dllfunc(DLLFunc_Spawn, ent)
  10075. dllfunc(DLLFunc_Use, ent, id)
  10076. engfunc(EngFunc_RemoveEntity, ent)
  10077. }
  10078.  
  10079. // Collect random spawn points
  10080. stock load_spawns()
  10081. {
  10082. // Check for CSDM spawns of the current map
  10083. new cfgdir[32], mapname[32], filepath[100], linedata[64]
  10084. get_configsdir(cfgdir, charsmax(cfgdir))
  10085. get_mapname(mapname, charsmax(mapname))
  10086. formatex(filepath, charsmax(filepath), "%s/csdm/%s.spawns.cfg", cfgdir, mapname)
  10087.  
  10088. // Load CSDM spawns if present
  10089. if (file_exists(filepath))
  10090. {
  10091. new csdmdata[10][6], file = fopen(filepath,"rt")
  10092.  
  10093. while (file && !feof(file))
  10094. {
  10095. fgets(file, linedata, charsmax(linedata))
  10096.  
  10097. // invalid spawn
  10098. if(!linedata[0] || str_count(linedata,' ') < 2) continue;
  10099.  
  10100. // get spawn point data
  10101. parse(linedata,csdmdata[0],5,csdmdata[1],5,csdmdata[2],5,csdmdata[3],5,csdmdata[4],5,csdmdata[5],5,csdmdata[6],5,csdmdata[7],5,csdmdata[8],5,csdmdata[9],5)
  10102.  
  10103. // origin
  10104. g_spawns[g_spawnCount][0] = floatstr(csdmdata[0])
  10105. g_spawns[g_spawnCount][1] = floatstr(csdmdata[1])
  10106. g_spawns[g_spawnCount][2] = floatstr(csdmdata[2])
  10107.  
  10108. // increase spawn count
  10109. g_spawnCount++
  10110. if (g_spawnCount >= sizeof g_spawns) break;
  10111. }
  10112. if (file) fclose(file)
  10113. }
  10114. else
  10115. {
  10116. // Collect regular spawns
  10117. collect_spawns_ent("info_player_start")
  10118. collect_spawns_ent("info_player_deathmatch")
  10119. }
  10120.  
  10121. // Collect regular spawns for non-random spawning unstuck
  10122. collect_spawns_ent2("info_player_start")
  10123. collect_spawns_ent2("info_player_deathmatch")
  10124. }
  10125.  
  10126. // Collect spawn points from entity origins
  10127. stock collect_spawns_ent(const classname[])
  10128. {
  10129. new ent = -1
  10130. while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", classname)) != 0)
  10131. {
  10132. // get origin
  10133. new Float:originF[3]
  10134. pev(ent, pev_origin, originF)
  10135. g_spawns[g_spawnCount][0] = originF[0]
  10136. g_spawns[g_spawnCount][1] = originF[1]
  10137. g_spawns[g_spawnCount][2] = originF[2]
  10138.  
  10139. // increase spawn count
  10140. g_spawnCount++
  10141. if (g_spawnCount >= sizeof g_spawns) break;
  10142. }
  10143. }
  10144.  
  10145. // Collect spawn points from entity origins
  10146. stock collect_spawns_ent2(const classname[])
  10147. {
  10148. new ent = -1
  10149. while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", classname)) != 0)
  10150. {
  10151. // get origin
  10152. new Float:originF[3]
  10153. pev(ent, pev_origin, originF)
  10154. g_spawns2[g_spawnCount2][0] = originF[0]
  10155. g_spawns2[g_spawnCount2][1] = originF[1]
  10156. g_spawns2[g_spawnCount2][2] = originF[2]
  10157.  
  10158. // increase spawn count
  10159. g_spawnCount2++
  10160. if (g_spawnCount2 >= sizeof g_spawns2) break;
  10161. }
  10162. }
  10163.  
  10164. // Drop primary/secondary weapons
  10165. stock drop_weapons(id, dropwhat)
  10166. {
  10167. // Get user weapons
  10168. static weapons[32], num, i, weaponid
  10169. num = 0 // reset passed weapons count (bugfix)
  10170. get_user_weapons(id, weapons, num)
  10171.  
  10172. // Loop through them and drop primaries or secondaries
  10173. for (i = 0; i < num; i++)
  10174. {
  10175. // Prevent re-indexing the array
  10176. weaponid = weapons[i]
  10177.  
  10178. if ((dropwhat == 1 && ((1<<weaponid) & PRIMARY_WEAPONS_BIT_SUM)) || (dropwhat == 2 && ((1<<weaponid) & SECONDARY_WEAPONS_BIT_SUM)))
  10179. {
  10180. // Get weapon entity
  10181. static wname[32], weapon_ent
  10182. get_weaponname(weaponid, wname, charsmax(wname))
  10183. weapon_ent = fm_find_ent_by_owner(-1, wname, id)
  10184.  
  10185. // Hack: store weapon bpammo on PEV_ADDITIONAL_AMMO
  10186. set_pev(weapon_ent, PEV_ADDITIONAL_AMMO, cs_get_user_bpammo(id, weaponid))
  10187.  
  10188. // Player drops the weapon and looses his bpammo
  10189. engclient_cmd(id, "drop", wname)
  10190. cs_set_user_bpammo(id, weaponid, 0)
  10191. }
  10192. }
  10193. }
  10194.  
  10195. // Stock by (probably) Twilight Suzuka -counts number of chars in a string
  10196. stock str_count(const str[], searchchar)
  10197. {
  10198. new count, i, len = strlen(str)
  10199.  
  10200. for (i = 0; i <= len; i++)
  10201. {
  10202. if(str[i] == searchchar)
  10203. count++
  10204. }
  10205.  
  10206. return count;
  10207. }
  10208.  
  10209. // Checks if a space is vacant (credits to VEN)
  10210. stock is_hull_vacant(Float:origin[3], hull)
  10211. {
  10212. engfunc(EngFunc_TraceHull, origin, origin, 0, hull, 0, 0)
  10213.  
  10214. if (!get_tr2(0, TR_StartSolid) && !get_tr2(0, TR_AllSolid) && get_tr2(0, TR_InOpen))
  10215. return true;
  10216.  
  10217. return false;
  10218. }
  10219.  
  10220. // Check if a player is stuck (credits to VEN)
  10221. stock is_player_stuck(id)
  10222. {
  10223. static Float:originF[3]
  10224. pev(id, pev_origin, originF)
  10225.  
  10226. engfunc(EngFunc_TraceHull, originF, originF, 0, (pev(id, pev_flags) & FL_DUCKING) ? HULL_HEAD : HULL_HUMAN, id, 0)
  10227.  
  10228. if (get_tr2(0, TR_StartSolid) || get_tr2(0, TR_AllSolid) || !get_tr2(0, TR_InOpen))
  10229. return true;
  10230.  
  10231. return false;
  10232. }
  10233.  
  10234. // Simplified get_weaponid (CS only)
  10235. stock cs_weapon_name_to_id(const weapon[])
  10236. {
  10237. static i
  10238. for (i = 0; i < sizeof WEAPONENTNAMES; i++)
  10239. {
  10240. if (equal(weapon, WEAPONENTNAMES[i]))
  10241. return i;
  10242. }
  10243.  
  10244. return 0;
  10245. }
  10246.  
  10247. // Get User Current Weapon Entity
  10248. stock fm_cs_get_current_weapon_ent(id)
  10249. {
  10250. return get_pdata_cbase(id, OFFSET_ACTIVE_ITEM, OFFSET_LINUX);
  10251. }
  10252.  
  10253. // Get Weapon Entity's Owner
  10254. stock fm_cs_get_weapon_ent_owner(ent)
  10255. {
  10256. return get_pdata_cbase(ent, OFFSET_WEAPONOWNER, OFFSET_LINUX_WEAPONS);
  10257. }
  10258.  
  10259. // Set User Deaths
  10260. stock fm_cs_set_user_deaths(id, value)
  10261. {
  10262. set_pdata_int(id, OFFSET_CSDEATHS, value, OFFSET_LINUX)
  10263. }
  10264.  
  10265. // Get User Team
  10266. stock fm_cs_get_user_team(id)
  10267. {
  10268. return get_pdata_int(id, OFFSET_CSTEAMS, OFFSET_LINUX);
  10269. }
  10270.  
  10271. // Set a Player's Team
  10272. stock fm_cs_set_user_team(id, team)
  10273. {
  10274. set_pdata_int(id, OFFSET_CSTEAMS, team, OFFSET_LINUX)
  10275. }
  10276.  
  10277. // Set User Money
  10278. stock fm_cs_set_user_money(id, value)
  10279. {
  10280. set_pdata_int(id, OFFSET_CSMONEY, value, OFFSET_LINUX)
  10281. }
  10282.  
  10283. // Set User Flashlight Batteries
  10284. stock fm_cs_set_user_batteries(id, value)
  10285. {
  10286. set_pdata_int(id, OFFSET_FLASHLIGHT_BATTERY, value, OFFSET_LINUX)
  10287. }
  10288.  
  10289. // Update Player's Team on all clients (adding needed delays)
  10290. stock fm_user_team_update(id)
  10291. {
  10292. static Float:current_time
  10293. current_time = get_gametime()
  10294.  
  10295. if (current_time - g_teams_targettime >= 0.1)
  10296. {
  10297. set_task(0.1, "fm_cs_set_user_team_msg", id+TASK_TEAM)
  10298. g_teams_targettime = current_time + 0.1
  10299. }
  10300. else
  10301. {
  10302. set_task((g_teams_targettime + 0.1) - current_time, "fm_cs_set_user_team_msg", id+TASK_TEAM)
  10303. g_teams_targettime = g_teams_targettime + 0.1
  10304. }
  10305. }
  10306.  
  10307. // Send User Team Message
  10308. public fm_cs_set_user_team_msg(taskid)
  10309. {
  10310. // Note to self: this next message can now be received by other plugins
  10311.  
  10312. // Set the switching team flag
  10313. g_switchingteam = true
  10314.  
  10315. // Tell everyone my new team
  10316. emessage_begin(MSG_ALL, g_msgTeamInfo)
  10317. ewrite_byte(ID_TEAM) // player
  10318. ewrite_string(CS_TEAM_NAMES[fm_cs_get_user_team(ID_TEAM)]) // team
  10319. emessage_end()
  10320.  
  10321. // Done switching team
  10322. g_switchingteam = false
  10323. }
  10324.  
  10325. // Set the precached model index (updates hitboxes server side)
  10326. stock fm_cs_set_user_model_index(id, value)
  10327. {
  10328. set_pdata_int(id, OFFSET_MODELINDEX, value, OFFSET_LINUX)
  10329. }
  10330.  
  10331. // Set Player Model on Entity
  10332. stock fm_set_playermodel_ent(id)
  10333. {
  10334. // Make original player entity invisible without hiding shadows or firing effects
  10335. fm_set_rendering(id, kRenderFxNone, 255, 255, 255, kRenderTransTexture, 1)
  10336.  
  10337. // Format model string
  10338. static model[100]
  10339. formatex(model, charsmax(model), "models/player/%s/%s.mdl", g_playermodel[id], g_playermodel[id])
  10340.  
  10341. // Set model on entity or make a new one if unexistant
  10342. if (!pev_valid(g_ent_playermodel[id]))
  10343. {
  10344. g_ent_playermodel[id] = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
  10345. if (!pev_valid(g_ent_playermodel[id])) return;
  10346.  
  10347. set_pev(g_ent_playermodel[id], pev_classname, MODEL_ENT_CLASSNAME)
  10348. set_pev(g_ent_playermodel[id], pev_movetype, MOVETYPE_FOLLOW)
  10349. set_pev(g_ent_playermodel[id], pev_aiment, id)
  10350. set_pev(g_ent_playermodel[id], pev_owner, id)
  10351. }
  10352.  
  10353. engfunc(EngFunc_SetModel, g_ent_playermodel[id], model)
  10354. }
  10355.  
  10356. // Set Weapon Model on Entity
  10357. stock fm_set_weaponmodel_ent(id)
  10358. {
  10359. // Get player's p_ weapon model
  10360. static model[100]
  10361. pev(id, pev_weaponmodel2, model, charsmax(model))
  10362.  
  10363. // Set model on entity or make a new one if unexistant
  10364. if (!pev_valid(g_ent_weaponmodel[id]))
  10365. {
  10366. g_ent_weaponmodel[id] = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
  10367. if (!pev_valid(g_ent_weaponmodel[id])) return;
  10368.  
  10369. set_pev(g_ent_weaponmodel[id], pev_classname, WEAPON_ENT_CLASSNAME)
  10370. set_pev(g_ent_weaponmodel[id], pev_movetype, MOVETYPE_FOLLOW)
  10371. set_pev(g_ent_weaponmodel[id], pev_aiment, id)
  10372. set_pev(g_ent_weaponmodel[id], pev_owner, id)
  10373. }
  10374.  
  10375. engfunc(EngFunc_SetModel, g_ent_weaponmodel[id], model)
  10376. }
  10377.  
  10378. // Remove Custom Model Entities
  10379. stock fm_remove_model_ents(id)
  10380. {
  10381. // Remove "playermodel" ent if present
  10382. if (pev_valid(g_ent_playermodel[id]))
  10383. {
  10384. engfunc(EngFunc_RemoveEntity, g_ent_playermodel[id])
  10385. g_ent_playermodel[id] = 0
  10386. }
  10387. // Remove "weaponmodel" ent if present
  10388. if (pev_valid(g_ent_weaponmodel[id]))
  10389. {
  10390. engfunc(EngFunc_RemoveEntity, g_ent_weaponmodel[id])
  10391. g_ent_weaponmodel[id] = 0
  10392. }
  10393. }
  10394.  
  10395. // Set User Model
  10396. public fm_cs_set_user_model(taskid)
  10397. {
  10398. set_user_info(ID_MODEL, "model", g_playermodel[ID_MODEL])
  10399. }
  10400.  
  10401. // Get User Model -model passed byref-
  10402. stock fm_cs_get_user_model(player, model[], len)
  10403. {
  10404. get_user_info(player, "model", model, len)
  10405. }
  10406.  
  10407. // Update Player's Model on all clients (adding needed delays)
  10408. public fm_user_model_update(taskid)
  10409. {
  10410. static Float:current_time
  10411. current_time = get_gametime()
  10412.  
  10413. if (current_time - g_models_targettime >= g_modelchange_delay)
  10414. {
  10415. fm_cs_set_user_model(taskid)
  10416. g_models_targettime = current_time
  10417. }
  10418. else
  10419. {
  10420. set_task((g_models_targettime + g_modelchange_delay) - current_time, "fm_cs_set_user_model", taskid)
  10421. g_models_targettime = g_models_targettime + g_modelchange_delay
  10422. }
  10423. }
  10424.  
Add Comment
Please, Sign In to add comment