Guest User

Untitled

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