diff --git a/README.md b/README.md index b77cfd02..da47ffdc 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ### Zombie Panic Mod for Counter-Strike 1.6 -__Version:__ 1.4.0 +__Version:__ 1.4.1 ### Download latest: - [Releases](../../releases) diff --git a/assets/addons/amxmodx/configs/zombiepanic.cfg b/assets/addons/amxmodx/configs/zombiepanic.cfg index 4475f80f..5411f605 100644 --- a/assets/addons/amxmodx/configs/zombiepanic.cfg +++ b/assets/addons/amxmodx/configs/zombiepanic.cfg @@ -13,11 +13,12 @@ zp_flashlight_recovery_rate 0.5 // [Zombie Panic] Gamerules zp_competitive 0 +zp_mapinfo 0 zp_zombie_lives 0 zp_zombie_lives_per_player 2 // [Zombie Panic] Infection -zp_infection_chance 10 +zp_infection_chance 5 // [Zombie Panic] Music zp_join_music 1 diff --git a/assets/addons/amxmodx/data/lang/zombiepanic.txt b/assets/addons/amxmodx/data/lang/zombiepanic.txt index ae7849fc..dccfefcf 100644 --- a/assets/addons/amxmodx/data/lang/zombiepanic.txt +++ b/assets/addons/amxmodx/data/lang/zombiepanic.txt @@ -2,7 +2,7 @@ ZP_HINT_TITLE = Hint ZP_HINT_PANIC = Panic may help you escape from the zombies^nPress to Panic ZP_HINT_DROP_AMMO = You can drop your ammo pressing ^nPress to select ammo type -ZP_HINT_PICKUP = Press to pickup items on dinstance +ZP_HINT_PICKUP = Press to pickup items on distance ZP_WARN_TITLE = Warning ZP_WARN_SPEED = A large amount of ammo and weapons slows you down^nDon't forget to get rid of unnecessary ammo ZP_OBJECTIVE_TITLE = Survival @@ -41,3 +41,25 @@ ZP_ITEM_PICKUP_TITLE = ZP_ITEM_PICKUP = Подобрать предмет ZP_WARN_INFECTION_TITLE = Заражение ZP_WARN_INFECTOR = Вы инфицировали игрока + +[hu] +ZP_HINT_TITLE = Tipp +ZP_HINT_PANIC = A Pánik segíthet a zombik előli menekülésben^nNyomd meg az gombot a Pánikhoz +ZP_HINT_DROP_AMMO = Eldobhatod a töltényeid az gombbal^nNyomd meg a gombot a töltény típus váltásához +ZP_HINT_PICKUP = Az gombbal felvehetsz távolabbi tárgyat is +ZP_WARN_TITLE = Figyelmeztetés +ZP_WARN_SPEED = Sok töltény és fegyver viselése lelassít^nDobd el a nem kellő töltényeket +ZP_OBJECTIVE_TITLE = Túlélő +ZP_OBJECTIVE_HUMAN = Éld túl a kört vagy ölj meg minden zombit +ZP_OBJECTIVE_ZOMBIE = Öld meg az összes túlélőt +ZPO_OBJECTIVE_TITLE = Feladat +ZPO_OBJECTIVE_HUMAN = Kövesd a jelölést a feladatok teljesítéséhez +ZPO_OBJECTIVE_ZOMBIE = Ne hagyd, hogy a túlélők feladatot teljesítsenek +ZP_RESPAWN_TITLE = Újraéledés +ZP_RESPAWN_ZOMBIE = Hamarosan újraéledsz...^nAz életek számát a jobb alsó sarokban látod +ZP_RESPAWN_HUMAN = Hamarosan újraéledsz zombiként... +ZP_RESPAWN_NOLIVES = Nincs több életed^nVárj további életek megjelenésére +ZP_ITEM_PICKUP_TITLE = +ZP_ITEM_PICKUP = Tárgy felvétele +ZP_WARN_INFECTION_TITLE = Fertőzés +ZP_WARN_INFECTOR = Megfertőzted a játékost \ No newline at end of file diff --git a/package.json b/package.json index 3e945ed5..a3af69ee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "zombiepanic", - "version": "1.4.0", + "version": "1.4.1", "description": "Zombie Panic Mod", "scripts": { "gulp": "gulp", diff --git a/src/include/zombiepanic.inc b/src/include/zombiepanic.inc index a9e22335..4bb01125 100644 --- a/src/include/zombiepanic.inc +++ b/src/include/zombiepanic.inc @@ -1,4 +1,23 @@ /* + 1.4.1 + Additions and improvements: + Reduced shotgun spread + Reduced shotgun range modifier + Reduced default infection chance + Map information is no longer showing by default + Bots can now pick multiple secondary weapons + Added hu localization (by regener) + + Cvars: + Added zp_mapinfo cvar + + Fixes: + Fixed satchels drop + Fixed and optimized objective marks + Fixed custom weapons prediction + Fixed bots interaction with doors blocked by master + Fixed en localization + 1.4.0 Additions and improvements: Infected players with symptoms can now pickup healthkit diff --git a/src/include/zombiepanic_const.inc b/src/include/zombiepanic_const.inc index 516b4faa..7ac942e2 100644 --- a/src/include/zombiepanic_const.inc +++ b/src/include/zombiepanic_const.inc @@ -1,5 +1,5 @@ #define ZP_TITLE "Zombie Panic" -#define ZP_VERSION "1.4.0" +#define ZP_VERSION "1.4.1" #define ZP_HUMAN_TEAM 2 #define ZP_ZOMBIE_TEAM 1 diff --git a/src/scripts/api/api_custom_weapons.sma b/src/scripts/api/api_custom_weapons.sma index b520aa77..33ea8def 100644 --- a/src/scripts/api/api_custom_weapons.sma +++ b/src/scripts/api/api_custom_weapons.sma @@ -18,6 +18,8 @@ #define VEC_DUCK_HULL_MIN Float:{-16.0, -16.0, -18.0} #define VEC_DUCK_HULL_MAX Float:{16.0, 16.0, 18.0} +#define IS_PLAYER(%1) (%1 > 0 && %1 <= MAX_PLAYERS) + #define TOKEN 743647146 enum CW_Data { @@ -100,6 +102,7 @@ new Trie:g_rgWeaponsMap; new g_iWeaponCount; new Float:g_flNextPredictionUpdate[MAX_PLAYERS + 1]; +new bool:g_bKnifeHolstered[MAX_PLAYERS + 1]; new g_iszWeaponBox; new g_pNewWeaponboxEnt = -1; @@ -120,7 +123,7 @@ public plugin_precache() { register_forward(FM_SetModel, "OnSetModel_Post", 1); register_forward(FM_DecalIndex, "OnDecalIndex_Post", 1); - RegisterHam(Ham_Spawn, "weaponbox", "OnWeaponboxSpawn_Post"); + RegisterHam(Ham_Spawn, "weaponbox", "OnWeaponboxSpawn", .Post = 0); RegisterHam(Ham_Player_PreThink, "player", "OnPlayerPreThink_Post", .Post = 1); RegisterHam(Ham_TakeDamage, "player", "OnPlayerTakeDamage", .Post = 0); RegisterHam(Ham_TakeDamage, "player", "OnPlayerTakeDamage_Post", .Post = 1); @@ -441,6 +444,10 @@ public Native_RemovePlayerItem(iPluginId, iArgc) { // ANCHOR: Forwards +public client_connect(pPlayer) { + g_bKnifeHolstered[pPlayer] = true; +} + public client_disconnected(pPlayer) { SetWeaponPrediction(pPlayer, true); } @@ -460,9 +467,7 @@ public OnItemDeploy(this) { public OnItemHolster(this) { new pPlayer = GetPlayer(this); - if (IsWeaponKnife(this)) { - g_flNextPredictionUpdate[pPlayer] = get_gametime() + 0.1; - } + g_bKnifeHolstered[pPlayer] = IsWeaponKnife(this); new CW:iHandler = GetHandlerByEntity(this); if (iHandler == CW_INVALID_HANDLER) { @@ -605,21 +610,29 @@ public OnSpawn_Post(this) { return HAM_IGNORED; } -public OnWeaponboxSpawn_Post(this) { +public OnWeaponboxSpawn(this) { g_pNewWeaponboxEnt = this; } public OnPlayerPreThink_Post(pPlayer) { - new pActiveItem = get_member(pPlayer, m_pActiveItem); + if (get_gametime() < g_flNextPredictionUpdate[pPlayer]) { + return HAM_IGNORED; + } + + new iObsMode = pev(pPlayer, pev_iuser1); + new pObsTarget = pev(pPlayer, pev_iuser2); + + new pActiveItem = iObsMode == OBS_IN_EYE + ? IS_PLAYER(pObsTarget) ? get_member(pObsTarget, m_pActiveItem) : -1 + : get_member(pPlayer, m_pActiveItem); + if (pActiveItem == -1) { SetWeaponPrediction(pPlayer, false); return HAM_IGNORED; } - if (get_gametime() >= g_flNextPredictionUpdate[pPlayer]) { - new CW:iHandler = GetHandlerByEntity(pActiveItem); - SetWeaponPrediction(pPlayer, iHandler == CW_INVALID_HANDLER); - } + new CW:iHandler = GetHandlerByEntity(pActiveItem); + SetWeaponPrediction(pPlayer, iHandler == CW_INVALID_HANDLER); return HAM_HANDLED; } @@ -910,6 +923,7 @@ WeaponIdle(this) { WeaponHolster(this) { new pPlayer = GetPlayer(this); + SetWeaponPrediction(pPlayer, true); set_member(this, m_Weapon_fInReload, 0); set_member(this, m_Weapon_fInSpecialReload, 0); @@ -926,8 +940,43 @@ WeaponDeploy(this) { } new pPlayer = GetPlayer(this); - if (get_gametime() >= g_flNextPredictionUpdate[pPlayer]) { + + if (g_bKnifeHolstered[pPlayer]) { + g_flNextPredictionUpdate[pPlayer] = get_gametime() + 1.0; + + for (new pSpectator = 1; pSpectator <= MaxClients; pSpectator++) { + if (!is_user_connected(pSpectator)) { + continue; + } + + if (pev(pSpectator, pev_iuser1) != OBS_IN_EYE) { + continue; + } + + if (pev(pSpectator, pev_iuser2) != pPlayer) { + continue; + } + + g_flNextPredictionUpdate[pSpectator] = get_gametime() + 1.0; + } + } else if (get_member(this, m_iId) == CSW_KNIFE) { SetWeaponPrediction(pPlayer, false); + + for (new pSpectator = 1; pSpectator <= MaxClients; pSpectator++) { + if (!is_user_connected(pSpectator)) { + continue; + } + + if (pev(pSpectator, pev_iuser1) != OBS_IN_EYE) { + continue; + } + + if (pev(pSpectator, pev_iuser2) != pPlayer) { + continue; + } + + SetWeaponPrediction(pSpectator, false); + } } // SetThink(this, "DisablePrediction"); diff --git a/src/scripts/core/zp_gamerules.sma b/src/scripts/core/zp_gamerules.sma index 9e4e7a8b..a6d4c742 100644 --- a/src/scripts/core/zp_gamerules.sma +++ b/src/scripts/core/zp_gamerules.sma @@ -29,6 +29,7 @@ enum TeamPreference { new g_pCvarLives; new g_pCvarLivesPerPlayer; new g_pCvarCompetitive; +new g_pCvarMapInfo; new g_pFwPlayerJoined; new g_pFwNewRound; @@ -45,7 +46,6 @@ public plugin_init() { Round_HookCheckWinConditions("OnCheckWinConditions"); - RegisterHam(Ham_Spawn, "player", "OnPlayerSpawn", .Post = 0); RegisterHam(Ham_Spawn, "player", "OnPlayerSpawn_Post", .Post = 1); RegisterHam(Ham_Killed, "player", "OnPlayerKilled_Post", .Post = 1); RegisterHam(Ham_TakeDamage, "player", "OnPlayerTakeDamage", .Post = 0); @@ -63,6 +63,7 @@ public plugin_init() { g_pCvarLives = register_cvar("zp_zombie_lives", "0"); g_pCvarLivesPerPlayer = register_cvar("zp_zombie_lives_per_player", "2"); g_pCvarCompetitive = register_cvar("zp_competitive", "0"); + g_pCvarMapInfo = register_cvar("zp_mapinfo", "0"); g_pFwPlayerJoined = CreateMultiForward("ZP_Fw_PlayerJoined", ET_IGNORE, FP_CELL); g_pFwNewRound = CreateMultiForward("ZP_Fw_NewRound", ET_IGNORE); @@ -258,14 +259,6 @@ public OnClientKill(pPlayer) { return get_member_game(m_bFreezePeriod) ? FMRES_SUPERCEDE : FMRES_IGNORED; } -public OnPlayerSpawn(pPlayer) { - if (!is_user_alive(pPlayer)) { - return HAM_IGNORED; - } - - return HAM_HANDLED; -} - public OnPlayerSpawn_Post(pPlayer) { if (!is_user_alive(pPlayer)) { return HAM_IGNORED; @@ -275,7 +268,9 @@ public OnPlayerSpawn_Post(pPlayer) { set_member(pPlayer, m_iTeam, ZP_HUMAN_TEAM); set_pev(pPlayer, pev_takedamage, DAMAGE_NO); OpenTeamMenu(pPlayer); - ZP_ShowMapInfo(pPlayer); + if (get_pcvar_num(g_pCvarMapInfo) > 0) { + ZP_ShowMapInfo(pPlayer); + } // ZP_Player_UpdateSpeed(pPlayer); } else { CheckWinConditions(); diff --git a/src/scripts/core/zp_infection.sma b/src/scripts/core/zp_infection.sma index ae936aff..5571ea0d 100644 --- a/src/scripts/core/zp_infection.sma +++ b/src/scripts/core/zp_infection.sma @@ -66,7 +66,7 @@ public plugin_init() { RegisterHam(Ham_TakeDamage, "player", "OnPlayerTakeDamage_Post", .Post = 0); RegisterHam(Ham_BloodColor, "player", "OnPlayerBloodColor", .Post = 0); - g_pCvarInfectionChance = register_cvar("zp_infection_chance", "10"); + g_pCvarInfectionChance = register_cvar("zp_infection_chance", "5"); g_pFwInfected = CreateMultiForward("ZP_Fw_PlayerInfected", ET_IGNORE, FP_CELL, FP_CELL); g_pFwCured = CreateMultiForward("ZP_Fw_PlayerCured", ET_IGNORE, FP_CELL); diff --git a/src/scripts/extra/zp_bot_fixes.sma b/src/scripts/extra/zp_bot_fixes.sma index dbd90712..8288952e 100644 --- a/src/scripts/extra/zp_bot_fixes.sma +++ b/src/scripts/extra/zp_bot_fixes.sma @@ -31,6 +31,7 @@ new CW:g_iCwSwipeHandler; new CW:g_iCwCrowbarHandler; new CW:g_iCwGrenadeHandler; new CW:g_iCwSatchelHandler; +new CW:g_iCwPistolHandler; new g_pCvarFixMeleeAttack; new g_pCvarFixPickup; @@ -49,9 +50,11 @@ public plugin_init() { g_iCwCrowbarHandler = CW_GetHandler(ZP_WEAPON_CROWBAR); g_iCwGrenadeHandler = CW_GetHandler(ZP_WEAPON_GRENADE); g_iCwSatchelHandler = CW_GetHandler(ZP_WEAPON_SATCHEL); + g_iCwPistolHandler = CW_GetHandler(ZP_WEAPON_PISTOL); RegisterHam(Ham_Touch, "weaponbox", "OnWeaponBoxTouch", .Post = 0); RegisterHam(Ham_Player_PreThink, "player", "OnPlayerPreThink_Post", .Post = 1); + RegisterHam(Ham_Use, "func_door", "OnDoorUse", .Post = 0); g_pCvarFixMeleeAttack = register_cvar("zp_bot_fix_melee_attack", "1"); g_pCvarFixPickup = register_cvar("zp_bot_fix_pickup", "1"); @@ -154,6 +157,25 @@ public OnPlayerPreThink_Post(pPlayer) { return HAM_HANDLED; } +public OnDoorUse(pDoor, pCaller, pActivator) { + if (!UTIL_IsPlayer(pActivator)) { + return HAM_IGNORED; + } + + if (!is_user_bot(pActivator)) { + return HAM_IGNORED; + } + + static szTargetname[32]; + pev(pDoor, pev_targetname, szTargetname, charsmax(szTargetname)); + + if (szTargetname[0] == '^0') { + return HAM_IGNORED; + } + + return HAM_SUPERCEDE; +} + DropActiveItem(pBot) { new pActiveItem = get_member(pBot, m_pActiveItem); @@ -313,12 +335,21 @@ bool:ShouldPickupWeaponBox(pBot, pWeaponBox, bool:bTouched) { continue; } - if (get_member(pBot, m_rgpPlayerItems, iSlot) != -1) { - return false; - } - + new pSlotItem = get_member(pBot, m_rgpPlayerItems, iSlot); new CW:iCwHandler = CW_GetHandlerByEntity(pItem); + if (pSlotItem != -1) { + new CW:iSlotCwHandler = CW_GetHandlerByEntity(pSlotItem); + + if (iCwHandler == iSlotCwHandler) { + return false; + } + + if (pSlotItem != -1 && iSlotCwHandler != g_iCwPistolHandler) { + return false; + } + } + // if (iCwHandler == g_iCwGrenadeHandler) { // return false; // } diff --git a/src/scripts/extra/zp_objective_marks.sma b/src/scripts/extra/zp_objective_marks.sma index e6144163..f7716127 100644 --- a/src/scripts/extra/zp_objective_marks.sma +++ b/src/scripts/extra/zp_objective_marks.sma @@ -17,11 +17,12 @@ #define SPRITE_HEIGHT 128.0 #define SPRITE_SCALE 0.03125 #define SPRITE_AMT 50.0 -#define MARK_UPDATE_DELAY 0.1 +#define MARK_UPDATE_DELAY 0.01 #define MARK_MAX_VELOCITY 250.0 #define MARK_MAX_MOVE_STEP_LENGTH 800.0 #define MARK_MAX_SCALE_STEP 0.125 #define MARK_MAX_SCALE_STEP_LENGTH 100.0 +#define MAX_PLAYER_MARKS 16 enum _:Frame { TopLeft, TopRight, BottomLeft, BottomRight }; @@ -35,12 +36,12 @@ enum PlayerData { new Array:g_irgMarks; new g_iMarkModelIndex; -new g_rgPlayerData[MAX_PLAYERS + 1][12][PlayerData]; +new g_rgPlayerData[MAX_PLAYERS + 1][MAX_PLAYER_MARKS][PlayerData]; new g_pCvarEnabled; public plugin_precache() { - g_irgMarks = ArrayCreate(); + g_irgMarks = ArrayCreate(_, MAX_PLAYER_MARKS); g_iMarkModelIndex = precache_model(ZP_OBJECTIVE_MARK_SPRITE); RegisterHam(Ham_Spawn, "func_button", "OnButtonSpawn_Post", .Post = 1); @@ -73,6 +74,15 @@ public plugin_end() { } public OnButtonSpawn_Post(pButton) { + if (ArraySize(g_irgMarks) >= MAX_PLAYER_MARKS) { + log_amx("WARNING: Objective marks limit reached!"); + return; + } + + if (~pev(pButton, pev_spawnflags) & ZP_BUTTON_FLAG_HUMAN_ONLY) { + return; + } + new pMark = CreateMark(pButton); set_pev(pMark, pev_iuser1, ArraySize(g_irgMarks)); ArrayPushCell(g_irgMarks, pMark); @@ -119,12 +129,12 @@ public OnAddToFullPack(es, e, pEntity, pHost, pHostFlags, pPlayer, pSet) { new pButton = pev(pEntity, pev_owner); new iMarkIndex = pev(pEntity, pev_iuser1); - if (!IsUsableObjective(pHost, pButton)) { + if (!UTIL_IsUsableButton(pButton, pHost)) { g_rgPlayerData[pHost][iMarkIndex][Player_MarkUpdateTime] = 0.0; return FMRES_SUPERCEDE; } - new Float:flDelta = get_gametime() - g_rgPlayerData[pPlayer][iMarkIndex][Player_MarkUpdateTime]; + new Float:flDelta = get_gametime() - g_rgPlayerData[pHost][iMarkIndex][Player_MarkUpdateTime]; if (!g_rgPlayerData[pHost][iMarkIndex][Player_MarkUpdateTime] || flDelta >= MARK_UPDATE_DELAY) { CalculateMark(pEntity, pHost); } @@ -299,19 +309,6 @@ CalculateMark(pMark, pPlayer) { g_rgPlayerData[pPlayer][iMarkIndex][Player_MarkUpdateTime] = get_gametime(); } -bool:IsUsableObjective(pPlayer, pButton) { - if (!UTIL_IsUsableButton(pButton, pPlayer)) { - return false; - } - - if (~pev(pButton, pev_spawnflags) & ZP_BUTTON_FLAG_HUMAN_ONLY) { - return false; - } - - return true; -} - - CreateFrame(const Float:vecOrigin[3], Float:flWidth, Float:flHeight, const Float:vecUp[3], const Float:vecRight[3], Float:rgvecFrameOut[Frame][3]) { new Float:flHalfWidth = flWidth / 2.0; new Float:flHalfHeight = flHeight / 2.0; diff --git a/src/scripts/weapons/zp_weapon_satchel.sma b/src/scripts/weapons/zp_weapon_satchel.sma index fcfdba9c..8f3e498b 100644 --- a/src/scripts/weapons/zp_weapon_satchel.sma +++ b/src/scripts/weapons/zp_weapon_satchel.sma @@ -154,7 +154,7 @@ public @Weapon_WeaponBoxSpawn(this, pWeaponBox) { public @Weapon_CanDrop(this) { new pPlayer = CW_GetPlayer(this); - return get_member(pPlayer, m_rgAmmo, g_iAmmoId) <= 0 ? PLUGIN_HANDLED : PLUGIN_CONTINUE; + return get_member(pPlayer, m_rgAmmo, g_iAmmoId) > 0 && !g_bPlayerChargeReady[pPlayer] ? PLUGIN_CONTINUE : PLUGIN_HANDLED; } Throw(this) { diff --git a/src/scripts/weapons/zp_weapon_shotgun.sma b/src/scripts/weapons/zp_weapon_shotgun.sma index 388ca35b..e260d870 100644 --- a/src/scripts/weapons/zp_weapon_shotgun.sma +++ b/src/scripts/weapons/zp_weapon_shotgun.sma @@ -48,9 +48,9 @@ public plugin_init() { public @Weapon_PrimaryAttack(this) { static Float:vecSpread[3]; - UTIL_CalculateWeaponSpread(this, Float:VECTOR_CONE_10DEGREES, 1.1125, 1.0, 0.95, 2.0, vecSpread); + UTIL_CalculateWeaponSpread(this, Float:VECTOR_CONE_8DEGREES, 1.1125, 1.0, 0.95, 2.0, vecSpread); - if (CW_DefaultShotgunShot(this, 6.0, 0.8, 1.0, 0.5, vecSpread, 25)) { + if (CW_DefaultShotgunShot(this, 6.0, 0.9, 1.0, 0.5, vecSpread, 25)) { CW_PlayAnimation(this, 1, 1.5); new pPlayer = CW_GetPlayer(this); emit_sound(pPlayer, CHAN_WEAPON, ZP_WEAPON_SHOTGUN_SHOT_SOUND, VOL_NORM, ATTN_NORM, 0, PITCH_NORM);