diff --git a/changelog.txt b/changelog.txt new file mode 100644 index 0000000..d7f2054 --- /dev/null +++ b/changelog.txt @@ -0,0 +1,15 @@ +2008.09.21 - 2.5.1.1 + * Added centered counter for spawn protection. + * Made chat commands visible to other players. + * Made unlimited ammo and hit sounds scripts part of the patch. + * Added public CVars zombie_enabled and zombie_version. + * IsClientConnected must always be before IsClientInGame, because IsClientInGame does not implicit call it. + +2008.09.20 - 2.5.1 + * Fixed spawn protection not protecting against zombies. + * Made protected players invisible and move faster. + * Changed class knockback to be a multiplier of the default knockback. + +2008.09.17 - 2.5.1 + * Added support for alpha values in classes. + diff --git a/src/zombiereloaded.sp b/src/zombiereloaded.sp index 51e591d..dbfa6e8 100644 --- a/src/zombiereloaded.sp +++ b/src/zombiereloaded.sp @@ -15,7 +15,7 @@ #undef REQUIRE_PLUGIN #include -#define VERSION "2.5.1" +#define VERSION "2.5.1.1" #include "zr/zombiereloaded" #include "zr/global" @@ -79,6 +79,8 @@ public OnPluginStart() // ====================================================================== CreateConVar("gs_zombiereloaded_version", VERSION, "[ZR] Current version of this plugin", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_UNLOGGED|FCVAR_DONTRECORD|FCVAR_REPLICATED|FCVAR_NOTIFY); + CreateConVar("zombie_version", VERSION, "Zombie:Reloaded Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_UNLOGGED|FCVAR_DONTRECORD|FCVAR_REPLICATED|FCVAR_NOTIFY); + CreateConVar("zombie_enabled", "1", "Not synced with zr_enable", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_UNLOGGED|FCVAR_DONTRECORD|FCVAR_REPLICATED|FCVAR_NOTIFY); // ====================================================================== @@ -192,7 +194,7 @@ ZREnd() new maxplayers = GetMaxClients(); for (new x = 1; x <= maxplayers; x++) { - if (!IsClientInGame(x)) + if (!IsClientConnected(x) || !IsClientInGame(x)) { continue; } diff --git a/src/zr/classes.inc b/src/zr/classes.inc index b9cc736..33e271e 100644 --- a/src/zr/classes.inc +++ b/src/zr/classes.inc @@ -26,7 +26,10 @@ enum ZR_ClassOptions Float:data_napalm_time, bool:data_nofalldamage, data_kill_bonus, - data_infect_health + data_infect_health, + data_alpha_spawn, + data_alpha_damaged, + data_alpha_damage } #define MAXCLASSES 20 @@ -104,6 +107,9 @@ LoadClassData() arrayClasses[classCount][data_nofalldamage] = bool:KvGetNum(kvClasses, "nofalldamage"), GetConVarBool(gCvars[CVAR_ZOMBIE_NOFALLDAMAGE]); arrayClasses[classCount][data_kill_bonus] = KvGetNum(kvClasses, "kill_bonus"), GetConVarInt(gCvars[CVAR_ZOMBIE_KILL_BONUS]); arrayClasses[classCount][data_infect_health] = KvGetNum(kvClasses, "infect_health"), GetConVarInt(gCvars[CVAR_ZOMBIE_INFECT_HEALTH]); + arrayClasses[classCount][data_alpha_spawn] = KvGetNum(kvClasses, "alpha_spawn"); + arrayClasses[classCount][data_alpha_damaged] = KvGetNum(kvClasses, "alpha_damaged"); + arrayClasses[classCount][data_alpha_damage] = KvGetNum(kvClasses, "alpha_damage"); classCount++; } while (KvGotoNextKey(kvClasses)); @@ -178,7 +184,7 @@ Float:GetClassKnockback(classindex) new bool:classes = GetConVarBool(gCvars[CVAR_CLASSES]); if (classes) { - return arrayClasses[classindex][data_knockback]; + return arrayClasses[classindex][data_knockback] * GetConVarFloat(gCvars[CVAR_ZOMBIE_KNOCKBACK]); } return GetConVarFloat(gCvars[CVAR_ZOMBIE_KNOCKBACK]); @@ -292,4 +298,35 @@ GetClassInfectHealth(classindex) } return GetConVarInt(gCvars[CVAR_ZOMBIE_INFECT_HEALTH]); -} \ No newline at end of file +} + +GetClassAlphaSpawn(classindex) +{ + new bool:classes = GetConVarBool(gCvars[CVAR_CLASSES]); + if (classes) { + return arrayClasses[classindex][data_alpha_spawn]; + } + + return 255; +} + +GetClassAlphaDamaged(classindex) +{ + new bool:classes = GetConVarBool(gCvars[CVAR_CLASSES]); + if (classes) { + return arrayClasses[classindex][data_alpha_damaged]; + } + + return 255; +} + +GetClassAlphaDamage(classindex) +{ + new bool:classes = GetConVarBool(gCvars[CVAR_CLASSES]); + if (classes) { + return arrayClasses[classindex][data_alpha_damage]; + } + + return 0; +} + diff --git a/src/zr/damagecontrol.inc b/src/zr/damagecontrol.inc index a6f8bef..1f537cd 100644 --- a/src/zr/damagecontrol.inc +++ b/src/zr/damagecontrol.inc @@ -24,8 +24,11 @@ new gHooks[MAXPLAYERS+1][ZRHooks]; InitDmgControl() { + /* It's case sensitive! */ RegConsoleCmd("kill", Attempt_Suicide); + RegConsoleCmd("KILL", Attempt_Suicide); RegConsoleCmd("jointeam", Attempt_Suicide); + RegConsoleCmd("JOINTEAM", Attempt_Suicide); RegConsoleCmd("spectate", Attempt_Suicide); } @@ -45,7 +48,7 @@ public TraceAttack(client, inflictor, attacker, damage, hitbox, hitgroup) { new bool:enabled = GetConVarBool(gCvars[CVAR_ENABLE]); - if (!attacker || !IsClientInGame(attacker) || !enabled) + if (!attacker || !IsClientConnected(attacker) || !IsClientInGame(attacker) || !enabled) { return Hacks_Continue; } diff --git a/src/zr/event.inc b/src/zr/event.inc index bc96752..9694ea6 100644 --- a/src/zr/event.inc +++ b/src/zr/event.inc @@ -214,6 +214,8 @@ public Action:PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) if (!StrEqual(respawnteam, "zombie", false)) { + SetPlayerAlpha(index, 0); + SetPlayerSpeed(index, 600.0); pProtect[index] = true; ZR_PrintToChat(index, "Spawn protection begin", protect); @@ -224,10 +226,18 @@ public Action:PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) CloseHandle(tHandles[index][TPROTECT]); } - tHandles[index][TPROTECT] = CreateTimer(float(protect), EndProtect, index, TIMER_FLAG_NO_MAPCHANGE); + protCount[index] = protect; + PrintHintText(index, "%d", protCount[index]); + protCount[index]--; + + tHandles[index][TPROTECT] = CreateTimer(1.0, EndProtect, index, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT); } } } + else + { + SetPlayerAlpha(index, 255); + } new bool:randomclass = GetConVarBool(gCvars[CVAR_CLASSES_RANDOM]); @@ -278,7 +288,7 @@ public Action:PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) { if (IsPlayerHuman(index) && IsPlayerZombie(attacker)) { - if (StrEqual(weapon, "knife")) + if (!pProtect[index] && StrEqual(weapon, "knife")) { Zombify(index, attacker); } @@ -346,6 +356,8 @@ public Action:PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) tHandles[index][TREGEN] = CreateTimer(interval, Regenerate, index, TIMER_REPEAT); } } + + UpdateAlphaDamaged(index); } FindExplodingGrenade(Float:heLoc[3]) diff --git a/src/zr/offsets.inc b/src/zr/offsets.inc index 646ed77..3cf8cb1 100644 --- a/src/zr/offsets.inc +++ b/src/zr/offsets.inc @@ -17,6 +17,8 @@ new offsCollision; new offsMoney; new offsFOV; new offsBuyZone; +new offsColor; +new offsRender; new Handle:hGameConf = INVALID_HANDLE; new Handle:hRemoveAllItems = INVALID_HANDLE; @@ -89,6 +91,16 @@ FindOffsets() { SetFailState("Couldn't find \"m_bInBuyZone\"!"); } + + offsColor = FindSendPropInfo("CAI_BaseNPC", "m_clrRender"); + if(offsColor == -1) { + SetFailState("Couldn't find \"m_clrRender\"!"); + } + + offsRender = FindSendPropInfo("CBaseAnimating", "m_nRenderMode"); + if(offsRender == -1) { + SetFailState("Couldn't find \"m_nRenderMode\"!"); + } } SetupGameData() @@ -187,4 +199,11 @@ SetPlayerModel(client, const String:model[]) { PrecacheModel(model); SetEntityModel(client, model); -} \ No newline at end of file +} + +SetPlayerAlpha(client, alpha) +{ + SetEntData(client, offsColor + 3, alpha, 1, true); + SetEntData(client, offsRender, 3, 1, true); +} + diff --git a/src/zr/sayhooks.inc b/src/zr/sayhooks.inc index 7212e95..eb5a82b 100644 --- a/src/zr/sayhooks.inc +++ b/src/zr/sayhooks.inc @@ -28,43 +28,36 @@ public Action:SayCommand(client, argc) if (StrEqual(args, "!zmenu", false)) { MainMenu(client); - return Plugin_Handled; } else if (StrEqual(args, "!zclass", false)) { ZClass(client); - return Plugin_Handled; } else if (StrEqual(args, "!zmarket", false)) { ZMarket(client); - return Plugin_Handled; } else if (StrEqual(args, "!zspawn", false)) { ZSpawn(client); - return Plugin_Handled; } else if (StrEqual(args, "!ztele", false)) { ZTele(client); - return Plugin_Handled; } else if (StrEqual(args, "!zstuck", false)) { ZStuck(client); - return Plugin_Handled; } else if (StrEqual(args, "!zhp", false)) { ZHP(client); - return Plugin_Handled; } return Plugin_Continue; diff --git a/src/zr/zombie.inc b/src/zr/zombie.inc index 210ccf7..f79a54e 100644 --- a/src/zr/zombie.inc +++ b/src/zr/zombie.inc @@ -178,6 +178,8 @@ Zombify_Mother(client) ApplyZombieModel(client); + ApplyZombieAlpha(client); + InfectionEffects(client); ZR_PrintToChat(client, "You are a zombie"); @@ -255,6 +257,8 @@ Zombify(client, attacker) ApplyZombieModel(client); + ApplyZombieAlpha(client); + if (bZVision[client]) { StartZVision(client); @@ -404,6 +408,12 @@ ApplyZombieFOV(client) SetPlayerFOV(client, fov); } +ApplyZombieAlpha(client) +{ + new alpha = GetClassAlphaSpawn(pClass[client]); + SetPlayerAlpha(client, alpha); +} + KnockBack(client, const Float:clientloc[3], const Float:attackerloc[3], Float:power, dmg, bool:boost) { if (!IsPlayerZombie(client)) @@ -443,7 +453,7 @@ JumpBoost(client, Float:distance, Float:height) PlayerLeft(client) { - if (!IsClientInGame(client)) + if (!IsClientConnected(client) || !IsClientInGame(client)) { return; } @@ -788,6 +798,18 @@ UpdateHPDisplay(client) ZR_HudHint(client, "Display HP", health); } +UpdateAlphaDamaged(client) +{ + new current_health = GetClientHealth(client); + new max_health = GetClassHealth(pClass[client]); + new max_damage = GetClassAlphaDamage(pClass[client]); + if (max_health - current_health > max_damage) + { + new alpha_damaged = GetClassAlphaDamaged(pClass[client]); + SetPlayerAlpha(client, alpha_damaged); + } +} + public Action:ZHPTimer(Handle:timer, any:index) { if (!IsClientInGame(index)) @@ -807,18 +829,29 @@ public Action:EndProtect(Handle:timer, any:index) if (!IsClientInGame(index)) { tHandles[index][TPROTECT] = INVALID_HANDLE; - - return; + return Plugin_Stop; } - pProtect[index] = false; + if (protCount[index] > 0) { + PrintHintText(index, "%d", protCount[index]); + protCount[index]--; + + return Plugin_Continue; + } else { + pProtect[index] = false; - if (IsPlayerHuman(index)) - { - ZR_PrintCenterText(index, "Spawn protection end"); + if (IsPlayerHuman(index)) + { + ZR_PrintCenterText(index, "Spawn protection end"); + } + + SetPlayerAlpha(index, 255); + SetPlayerSpeed(index, 300.0); + + tHandles[index][TPROTECT] = INVALID_HANDLE; + + return Plugin_Stop; } - - tHandles[index][TPROTECT] = INVALID_HANDLE; } RespawnPlayer(client) @@ -884,4 +917,4 @@ ZTeam:GetPlayerZTeam(client) } return Human; -} \ No newline at end of file +} diff --git a/src/zr/zombiereloaded.inc b/src/zr/zombiereloaded.inc index 1e8a1fa..64ff434 100644 --- a/src/zr/zombiereloaded.inc +++ b/src/zr/zombiereloaded.inc @@ -50,6 +50,7 @@ new pClass[MAXPLAYERS+1]; new pNextClass[MAXPLAYERS+1]; new teleCount[MAXPLAYERS+1]; +new protCount[MAXPLAYERS+1]; new Float:spawnLoc[MAXPLAYERS+1][3]; new Handle:tRound = INVALID_HANDLE; diff --git a/src/zr_ammo.sp b/src/zr_ammo.sp new file mode 100644 index 0000000..32adcf8 --- /dev/null +++ b/src/zr_ammo.sp @@ -0,0 +1,62 @@ + +#include + +/* +thx to Infinite Ammo by twistedeuphoria - http://forums.alliedmods.net/showthread.php?t=55381 +*/ + +public Plugin:myinfo = { + name = "Ammo Script for Zombie:Reloaded", + author = "[SG-10]Cpt.Moore", + description = "", + version = "1.0", + url = "http://zombie.swissquake.ch/" +}; + +new activeOffset = -1; +new clip1Offset = -1; +new clip2Offset = -1; +new secAmmoTypeOffset = -1; +new priAmmoTypeOffset = -1; + +// native hooks + +public OnPluginStart() +{ + HookEvent("weapon_fire", Event_WeaponFire); + activeOffset = FindSendPropOffs("CAI_BaseNPC", "m_hActiveWeapon"); + + clip1Offset = FindSendPropOffs("CBaseCombatWeapon", "m_iClip1"); + clip2Offset = FindSendPropOffs("CBaseCombatWeapon", "m_iClip2"); + + priAmmoTypeOffset = FindSendPropOffs("CBaseCombatWeapon", "m_iPrimaryAmmoCount"); + secAmmoTypeOffset = FindSendPropOffs("CBaseCombatWeapon", "m_iSecondaryAmmoCount"); +} + +// event hooks + +public Event_WeaponFire(Handle:event, const String:name[], bool:dontBroadcast) +{ + new userid = GetEventInt(event, "userid"); + new client = GetClientOfUserId(userid); + if(!IsFakeClient(client)) + { + Client_ResetAmmo(client); + } +} + +// helpers + +public Client_ResetAmmo(client) +{ + new zomg = GetEntDataEnt(client, activeOffset); + if (clip1Offset != -1) + SetEntData(zomg, clip1Offset, 104, 4, true); + if (clip2Offset != -1) + SetEntData(zomg, clip2Offset, 104, 4, true); + if (priAmmoTypeOffset != -1) + SetEntData(zomg, priAmmoTypeOffset, 200, 4, true); + if (secAmmoTypeOffset != -1) + SetEntData(zomg, secAmmoTypeOffset, 200, 4, true); +} + diff --git a/src/zr_hitsounds.sp b/src/zr_hitsounds.sp new file mode 100644 index 0000000..88b4c7b --- /dev/null +++ b/src/zr_hitsounds.sp @@ -0,0 +1,59 @@ + +#include +#include + +public Plugin:myinfo = { + name = "Hit Sounds for Zombie:Reloaded", + author = "[SG-10]Cpt.Moore", + description = "", + version = "1.0", + url = "http://zombie.swissquake.ch/" +}; + +static const String:hit_head[] = {"hit_head.wav"}; +static const String:hit_body[] = {"hit_body.wav"}; + +// native hooks +public OnPluginStart() +{ + HookEvent("player_hurt", Event_PlayerHurt); + LoadSound(hit_head); + LoadSound(hit_body); +} + +public OnMapStart() +{ + LoadSound(hit_head); + LoadSound(hit_body); +} + +public Event_PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) +{ + new attackerId = GetEventInt(event, "attacker"); + new attacker = GetClientOfUserId(attackerId); + //new damage = GetEventInt(event, "dmg_health"); + new hitgroup = GetEventInt(event,"hitgroup"); + + if( attacker > 0 && !IsFakeClient(attacker) ) + { + if ( hitgroup == 1 ) + { + EmitSoundToClient(attacker, hit_head); + } + else + { + EmitSoundToClient(attacker, hit_body); + } + } +} + +// utility functions + +public LoadSound(const String:sound_file[]) +{ + new String:sound_path[PLATFORM_MAX_PATH]; + Format(sound_path, sizeof(sound_path), "sound/%s", sound_file); + PrecacheSound(sound_file, true); + AddFileToDownloadsTable(sound_path); +} + diff --git a/src/zr_info.sp b/src/zr_info.sp new file mode 100644 index 0000000..144b6f6 --- /dev/null +++ b/src/zr_info.sp @@ -0,0 +1,52 @@ + +#include + +public Plugin:myinfo = { + name = "Info Script for Zombie:Reloaded", + author = "[SG-10]Cpt.Moore", + description = "", + version = "1.0", + url = "http://zombie.swissquake.ch/" +}; + +public OnPluginStart() +{ + RegConsoleCmd("sm_show_cvar", Command_Show_CVar); +} + +new String:g_sCVar[128]; +new String:g_sCVarValue[128]; +new Handle:g_hCVar; + +public Action:Command_Show_CVar(client,args) +{ + GetCmdArgString(g_sCVar,sizeof(g_sCVar)); + + g_hCVar = FindConVar(g_sCVar); + if (g_hCVar != INVALID_HANDLE) + { //not found + GetConVarString(g_hCVar, g_sCVarValue, sizeof(g_sCVarValue)); + if (client == 0) + { + PrintToServer("\"%s\" = \"%s\"", g_sCVar, g_sCVarValue); + } + else + { + PrintToConsole(client, "\"%s\" = \"%s\"", g_sCVar, g_sCVarValue); + } + } + else + { //found + if (client == 0) + { + PrintToServer("Couldn't find %s", g_sCVar); + } + else + { + PrintToConsole(client,"Couldn't find %s", g_sCVar); + } + } + + return Plugin_Handled; +} + diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000..0d4e8d9 --- /dev/null +++ b/todo.txt @@ -0,0 +1,31 @@ + + * Zombie dont have fall damage (damage by player 0 = server should always work) -> make it a CVAR, so for example zombies can't kill themselfs on same maps by going through lasers. + +---- CRITICAL/IMPORTANT ---- + +* FIXED -- fix spawn protection + players gets invisible, but not protected against zombies. + the array pProtect isn't used at all, just set to off and on. + +* DONE -- classes.inc:GetClassKnockback + change class knockback to be a miltiplier of the default knockback (like the old ZR), not absolute values: + knockback = default * class knockback + + +---- LOW PRIORITY ---- + +* zombie.inc:KnockBack / cvars.inc + make cvar for shotgun/hegrenade knockback boost. + +* make a admin command for reloading class data. useful when fine tuning knockback. + + and even better, if worth it: + make admin commands for getting and setting each class knockback, like: + SetClassKnockback(classindex, knockback) + GetClassKnockback(classindex) - already there, just need to hook a admin command too + + cvars.inc:EnableHook + another solution: + zr_enable: disable: a "round draw" occour, then it's regular cs. + enable: a new "round draw" occour and it's back. + not sure if classes are reloaded. if LoadClassData can be executed twice there's no problem.