New Member
|
02-02-2018
, 10:59
Re: [CS:GO] VIP Mode - GO:VIP
|
#36
|
Attachment 168347
Quote:
Originally Posted by Azet
I've compiled this with custom model for CS:GO and the two crucial things don't work:
- killing VIP doesn't end round (e.g slaying all other CTs)
- rescue zone doesn't work (tested on as_vertigo)
Only things that seem to work are:
- changing model for VIP
- VIP can only carry pistol and has 200 armor points (or HP, I can't remember)
- chat messages
|
Have you set up your config/rescue_zones.cfg file correctly?
You have to input the coordinates and radius of the rescue zone for each map in this file for it to work.
Also CS:GO might have some different EVENT types than SOURCE, so... my code might not work on GO.
It would require extensive modification of the scoring system this plugin uses. Might be someone who
wants to make it for CSGO
Take a look at the RoundEnd event and its reasons, team indexes, etc. for csgo and compare. If something differs within the code, then it needs be changed to the correct value.
Here's how I've set up my rescue_zones.cfg file for some custom maps and it works without a hitch.
Code:
"RescueZones"
{
"as_oilrig"
{
"Rescue Zone"
{
"coords" "-568.66 -1258.23 464.03"
}
}
"as_hiekka"
{
"Rescue Zone"
{
"coords" "-4492.53 1244.71 65.03"
}
"Rescue Zone"
{
"coords" "-3931.51 -1.33 -123.97"
}
}
"as_isku"
{
"Rescue Zone"
{
"coords" "-283.29 -1205.43 20.03"
"radius" "110"
}
}
}
That's addons/sourcemod/configs/rescue_zones.cfg
EDIT/P.S.:
The problem with no round ending on kill was prominent in CS:Source, and was apparently from a faulty line of code in the main function of the plugin. Everything works now. Here's the code:
PHP Code:
/** * 00. Includes * 01. Globals * 02. Forwards * 03. Events * 04. Functions */ // 00. Includes #include <sourcemod> #include <sdktools> #include <sdktools_functions> #include <sdkhooks> #include <clients> #include <cstrike>
// 01. Globals #define GOVIP_MAINLOOP_INTERVAL 0.1 #define GOVIP_MAXPLAYERS 64 #define IN 0x0001 #define OUT 0x0002
// We don't need them, since we #included <cstrike>, // but if something goes wrong, uncomment them. // #define CS_TEAM_CT 3 // #define CS_TEAM_T 2
enum VIPState { VIPState_WaitingForMinimumPlayers = 0, VIPState_Playing };
new CurrentVIP = 0; new LastVIP = 0; new VIPState:CurrentState = VIPState_WaitingForMinimumPlayers; new Handle:CVarMinCT = INVALID_HANDLE; new Handle:CVarMinT = INVALID_HANDLE; new Handle:CVarVIPWeapon = INVALID_HANDLE;
// We're declaring the new cvars here: new Handle:CVarVIPhp = INVALID_HANDLE; new Handle:CVarVIPreward = INVALID_HANDLE; new Handle:CVarVIParmor = INVALID_HANDLE; // End new cvar declaration
new MyWeaponsOffset = 0; new Handle:RescueZones = INVALID_HANDLE; new bool:RoundComplete = false;
/* We're using this for proper monetary reward (on roundstart) if you think it's lame and I should use get event winner instead, feel free to change the code to your liking. */ new winner = 0; // End of monetary reward check.
// Obviously these variables would affect the scoring system. // If you can code it better - be my guest. new CTscore = 0; new t_incScore = 0; new ct_incScore = 0; // End of scoring variables declaration
// 02. Forwards public OnPluginStart() { CVarMinCT = CreateConVar("govip_min_ct", "2", "Minimum number of CTs to play GOVIP"); CVarMinT = CreateConVar("govip_min_t", "1", "Minimum number of Ts to play GOVIP"); CVarVIPWeapon = CreateConVar("govip_weapon", "weapon_p250", "Weapon given to VIP"); CVarVIPhp = CreateConVar("govip_health", "200", "VIP Base Health"); CVarVIPreward = CreateConVar("govip_reward", "2500", "Money reward for winning by Escaping(CT) or killing the VIP(T)"); CVarVIParmor = CreateConVar("govip_armor", "100", "VIP Base Armor"); CurrentState = VIPState_WaitingForMinimumPlayers;
HookEvent("round_start", Event_RoundStart); HookEvent("player_death", Event_PlayerDeath, EventHookMode_Pre); HookEvent("round_end", Event_RoundEnd); new Handle:cvar_restartgame = FindConVar("mp_restartgame"); HookConVarChange(cvar_restartgame, ConVarChanged_Restartgame); MyWeaponsOffset = FindSendPropInfo("CBaseCombatCharacter", "m_hMyWeapons"); RescueZones = CreateArray(); RoundComplete = false; }
public OnClientPutInServer(client) { SDKHook(client, SDKHook_WeaponCanUse, OnWeaponCanUse); return; }
public OnClientDisconnect(client) { if(CurrentState != VIPState_Playing || client != CurrentVIP || RoundComplete) { return; } RoundComplete = true; LastVIP = CurrentVIP; CurrentVIP = 0; PrintToChatAll("%s", "[GO:VIP] The VIP has left, round ends in a draw."); CS_TerminateRound(3.0, CSRoundEnd_Draw); winner = 0;
}
public OnMapStart() {
t_incScore = 0; ct_incScore = 0; CTscore = 0;
new String:buffer[512]; PrecacheModel("models/player/vip/vip.mdl", true); PrecacheSound("govip/com_eliminatevip.wav", true); PrecacheSound("govip/com_killthatvip.wav", true); PrecacheSound("govip/com_keepvipsafe.wav", true); PrecacheSound("govip/com_protectvip.wav", true); PrecacheSound("govip/vip_assassinated.wav", true); PrecacheSound("govip/vip_escaped.wav", true); AddFileToDownloadsTable("materials/models/player/stenli/aliens/bishop/body.vmt"); AddFileToDownloadsTable("materials/models/player/stenli/aliens/bishop/body.vtf"); AddFileToDownloadsTable("materials/models/player/stenli/aliens/bishop/body_n.vtf"); AddFileToDownloadsTable("materials/models/player/stenli/aliens/bishop/head.vmt"); AddFileToDownloadsTable("materials/models/player/stenli/aliens/bishop/head.vtf"); AddFileToDownloadsTable("materials/models/player/stenli/aliens/bishop/head_n.vtf"); AddFileToDownloadsTable("materials/models/player/stenli/aliens/bishop/head_s.vtf"); AddFileToDownloadsTable("materials/models/player/stenli/aliens/bishop/hair.vmt"); AddFileToDownloadsTable("materials/models/player/stenli/aliens/bishop/hair.vtf"); AddFileToDownloadsTable("models/player/vip/vip.dx80.vtx"); AddFileToDownloadsTable("models/player/vip/vip.dx90.vtx"); AddFileToDownloadsTable("models/player/vip/vip.mdl"); AddFileToDownloadsTable("models/player/vip/vip.phy"); AddFileToDownloadsTable("models/player/vip/vip.sw.vtx"); AddFileToDownloadsTable("models/player/vip/vip.vvd"); AddFileToDownloadsTable("sound/govip/com_eliminatevip.wav"); AddFileToDownloadsTable("sound/govip/com_killthatvip.wav"); AddFileToDownloadsTable("sound/govip/com_keepvipsafe.wav"); AddFileToDownloadsTable("sound/govip/com_protectvip.wav"); AddFileToDownloadsTable("sound/govip/vip_assassinated.wav"); AddFileToDownloadsTable("sound/govip/vip_escaped.wav"); new trigger = -1; while((trigger = FindEntityByClassname(trigger, "trigger_multiple")) != -1) { GetEntPropString(trigger, Prop_Data, "m_iName", buffer, sizeof(buffer)); if(StrContains(buffer, "vip_rescue_zone", false) == 0) { SDKHook(trigger, SDKHook_Touch, TouchRescueZone); } } ClearArray(RescueZones); GetCurrentMap(buffer, sizeof(buffer)); new Handle:kv = CreateKeyValues("RescueZones"); new String:path[1024]; BuildPath(Path_SM, path, sizeof(path), "configs/rescue_zones.cfg"); FileToKeyValues(kv, path); if(KvJumpToKey(kv, buffer)) { KvGotoFirstSubKey(kv); do { new Float:radius = KvGetFloat(kv, "radius", 200.0); KvGetString(kv, "coords", buffer, sizeof(buffer)); new String:coords[3][128]; ExplodeString(buffer, " ", coords, 3, 128);
PrintToServer("[GO:VIP] Loading rescue zone at [%s, %s, %s] with radius of %f units.", coords[0], coords[1], coords[2], radius); new Handle:rescueZone = CreateArray(); PushArrayCell(rescueZone, radius); PushArrayCell(rescueZone, StringToFloat(coords[0])); PushArrayCell(rescueZone, StringToFloat(coords[1])); PushArrayCell(rescueZone, StringToFloat(coords[2])); PushArrayCell(RescueZones, rescueZone); } while (KvGotoNextKey(kv)); CreateTimer(GOVIP_MAINLOOP_INTERVAL, GOVIP_MainLoop, INVALID_HANDLE, TIMER_REPEAT); } else { PrintToServer("[GO:VIP] Map has no rescue zones, cannot start."); CurrentState = VIPState_WaitingForMinimumPlayers; } CloseHandle(kv);
}
// 03. Events public Action:Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast) { if (CurrentState == VIPState_Playing) { for (new i = 1; i <= MaxClients; i++) { if (IsClientInGame(i) && IsPlayerAlive(i)) { FreezePlayer(i); } } // Begin scoring system new roundwinner = GetEventInt(event, "winner"); // We're simply getting the reason for TerminateRound, then using hard-coded values for the scoring. // Not very 1337, but works like a bi0tch. new winreason = GetEventInt(event, "reason"); // Now we set conditions and do simple math. if (roundwinner == 2 && winreason == 2) { t_incScore++; SetTeamScore(CS_TEAM_CT, ct_incScore); SetTeamScore(CS_TEAM_T, t_incScore); } if (roundwinner == 3 && winreason == 7) { if (ct_incScore < CTscore) { ct_incScore = CTscore; } if (ct_incScore >= CTscore) { ct_incScore++; CTscore = ct_incScore;
} SetTeamScore(CS_TEAM_CT, ct_incScore); SetTeamScore(CS_TEAM_T, t_incScore); } if (roundwinner == 3 && winreason == 1) { ct_incScore++; CTscore = ct_incScore; SetTeamScore(CS_TEAM_CT, ct_incScore); SetTeamScore(CS_TEAM_T, t_incScore); } if (winreason == 15 || winreason == 9) { ct_incScore = 0; t_incScore = 0; CTscore = 0; } // End of scoring system. } return Plugin_Continue; } public Action:Event_RoundStart(Handle:event, const String:name[], bool:dontBroadcast) { if(CurrentState != VIPState_Playing) { PrintToChatAll("[GO:VIP] Map has no rescue zones - cannot start."); CurrentState = VIPState_WaitingForMinimumPlayers; return Plugin_Continue; } else { RoundComplete = false; CurrentVIP = GetRandomPlayerOnTeam(CS_TEAM_CT, LastVIP); new playercashoffs = FindSendPropInfo("CCSPlayer", "m_iAccount"); for (new i = 1; i <= MaxClients; i++) { if (IsClientInGame(i) && IsPlayerAlive(i)) { UnFreezePlayer(i); new pl_team = GetClientTeam(i); new iWeapon = GetPlayerWeaponSlot(i, 4); new playercash = GetEntData(i, playercashoffs); new cashreward; if (iWeapon != -1 && IsValidEdict(iWeapon)) { decl String:szClassName[64]; GetEdictClassname(iWeapon, szClassName, sizeof(szClassName)); if (StrEqual(szClassName, "weapon_c4", false)) { RemovePlayerItem(i, iWeapon); RemoveEdict(iWeapon); } } if (winner == 0 && pl_team == 2) { PrintCenterText(i, "Team, eliminate the VIP."); EmitSoundToClient(i, "govip/com_eliminatevip.wav", _, _, _, _, 1.0, _, _, _, _, _, _); } if (winner == 0 && pl_team == 3) { PrintCenterText(i, "Keep the VIP safe."); EmitSoundToClient(i, "govip/com_keepvipsafe.wav", _, _, _, _, 1.0, _, _, _, _, _, _); } if (winner == 1 && pl_team == 2) { cashreward = playercash + GetConVarInt(CVarVIPreward); SetEntData(i, playercashoffs, cashreward); PrintCenterText(i, "Team, eliminate the VIP."); EmitSoundToClient(i, "govip/com_eliminatevip.wav", _, _, _, _, 1.0, _, _, _, _, _, _); } if (winner == 22 && pl_team == 2) { cashreward = playercash - GetConVarInt(CVarVIPreward); if (playercash >= GetConVarInt(CVarVIPreward)) { SetEntData(i, playercashoffs, cashreward); } else { SetEntData(i, playercashoffs, 0); } PrintCenterText(i, "Kill that VIP at all costs!"); EmitSoundToClient(i, "govip/com_killthatvip.wav", _, _, _, _, 1.0, _, _, _, _, _, _); } if (winner == 22 && pl_team == 3) { cashreward = playercash + GetConVarInt(CVarVIPreward); SetEntData(i, playercashoffs, cashreward); PrintCenterText(i, "Keep the VIP safe."); EmitSoundToClient(i, "govip/com_keepvipsafe.wav", _, _, _, _, 1.0, _, _, _, _, _, _); } if (winner == 1 && pl_team == 3) { cashreward = playercash - GetConVarInt(CVarVIPreward); if (playercash >= GetConVarInt(CVarVIPreward)) { SetEntData(i, playercashoffs, cashreward); } else { SetEntData(i, playercashoffs, 0); } PrintCenterText(i, "Team, protect the VIP at all cost."); EmitSoundToClient(i, "govip/com_protectvip.wav", _, _, _, _, 1.0, _, _, _, _, _, _); } } } RemoveMapObj(); if(CurrentVIP == 0 || !IsValidPlayer(CurrentVIP)) { return Plugin_Continue; } new String:VIPName[128]; GetClientName(CurrentVIP, VIPName, sizeof(VIPName)); PrintToChatAll("[GO:VIP] \"%s\" is the VIP, CTs protect the VIP from the Terrorists!", VIPName); new String:VIPWeapon[256]; new basehp = GetConVarInt(CVarVIPhp); new basearmor = GetConVarInt(CVarVIParmor);
GetConVarString(CVarVIPWeapon, VIPWeapon, sizeof(VIPWeapon)); new ArmorOffs = FindSendPropInfo("CCSPlayer", "m_ArmorValue"); new HelmetOffs = FindSendPropInfo("CCSPlayer", "m_bHasHelmet"); new PMIndex = FindEntityByClassname(0, "cs_player_manager"); new index = CreateEntityByName(VIPWeapon); if(index != -1) { StripWeapons(CurrentVIP); SetEntityModel(CurrentVIP, "models/player/vip/vip.mdl"); GivePlayerItem(CurrentVIP, VIPWeapon); SDKHook(PMIndex, SDKHook_ThinkPost, OnThinkPost); if (basehp < 1) { SetEntityHealth(CurrentVIP, 1); } if (basehp > 200) { SetEntityHealth(CurrentVIP, 200); } if (basehp >=1 && basehp <= 200) { SetEntityHealth(CurrentVIP, basehp); } if (basearmor > 125) { SetEntData(CurrentVIP, ArmorOffs, 125); SetEntData(CurrentVIP, HelmetOffs, 1); } if (basearmor <= 125 && basearmor > 0) { SetEntData(CurrentVIP, ArmorOffs, basearmor); SetEntData(CurrentVIP, HelmetOffs, 1); } else { SetEntData(CurrentVIP, ArmorOffs, 0); SetEntData(CurrentVIP, HelmetOffs, 0); } } // You noticed? Leave it that way if you know what's good for your scoreboard. SetTeamScore(CS_TEAM_T, t_incScore); SetTeamScore(CS_TEAM_CT, ct_incScore); // End of duplicate. winner = 0; return Plugin_Continue; } }
public OnThinkPost(entity) { SetEntProp(entity, Prop_Send, "m_iPlayerVIP", CurrentVIP); }
public Action:Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) { if(CurrentState != VIPState_Playing) { return Plugin_Continue; } new userid = GetEventInt(event, "userid"); new client = GetClientOfUserId(userid); if(client != CurrentVIP || RoundComplete) { return Plugin_Continue; } RoundComplete = true; winner = 1; CS_TerminateRound(3.0, CSRoundEnd_VIPKilled); for (new i = 1; i <= MaxClients; i++) { if (IsClientInGame(i)) { EmitSoundToClient(i, "govip/vip_assassinated.wav", _, _, _, _, 1.0, _, _, _, _, _, _); } } PrintCenterTextAll("VIP has been assassinated!"); PrintToChatAll("%s", "[GO:VIP] The VIP has died, Terrorists win!"); LastVIP = CurrentVIP; CurrentVIP = 0; return Plugin_Continue; }
// 04. Functions public Action:GOVIP_MainLoop(Handle:timer) { new CTCount = GetTeamClientCount(CS_TEAM_CT); new TCount = GetTeamClientCount(CS_TEAM_T); if(CurrentState == VIPState_WaitingForMinimumPlayers) { if(CTCount >= GetConVarInt(CVarMinCT) && TCount >= GetConVarInt(CVarMinT)) { CurrentState = VIPState_Playing; PrintToChatAll("%s", "[GO:VIP] Starting the game!"); CS_TerminateRound(3.0, CSRoundEnd_GameStart); return Plugin_Continue; } } else if(CurrentState == VIPState_Playing) { if(TCount < GetConVarInt(CVarMinT) || CTCount < GetConVarInt(CVarMinCT)) { CurrentState = VIPState_WaitingForMinimumPlayers; PrintToChatAll("%s", "[GO:VIP] Game paused, waiting for more players."); return Plugin_Continue; } if(CurrentVIP == 0 && RoundComplete == false) { RoundComplete = true; CurrentVIP = GetRandomPlayerOnTeam(CS_TEAM_CT, LastVIP); winner = 0; CS_TerminateRound(3.0, CSRoundEnd_GameStart); } else if(!RoundComplete && IsValidPlayer(CurrentVIP)) { new Float:vipOrigin[3]; GetClientAbsOrigin(CurrentVIP, vipOrigin); new rescueZoneCount = GetArraySize(RescueZones); for(new rescueZoneIndex = 0; rescueZoneIndex < rescueZoneCount; rescueZoneIndex++) { new Handle:rescueZone = GetArrayCell(RescueZones, rescueZoneIndex); new Float:rescueZoneOrigin[3]; rescueZoneOrigin[0] = GetArrayCell(rescueZone, 1); rescueZoneOrigin[1] = GetArrayCell(rescueZone, 2); rescueZoneOrigin[2] = GetArrayCell(rescueZone, 3); new Float:rescueZoneRadius = GetArrayCell(rescueZone, 0); if(GetVectorDistance(rescueZoneOrigin, vipOrigin) <= rescueZoneRadius) { RoundComplete = true; EmitSoundToAll("govip/vip_escaped.wav", _, _, _, _, 1.0, _, _, _, _, _, _); LastVIP = CurrentVIP; winner = 22;
CS_TerminateRound(3.0, CSRoundEnd_VIPEscaped); for (new i = 1; i <= MaxClients; i++) { if (IsClientInGame(i)) { EmitSoundToClient(i, "govip/vip_escaped.wav", _, _, _, _, 1.0, _, _, _, _, _, _); } } PrintCenterTextAll("The VIP Escaped!"); PrintToChatAll("%s", "[GO:VIP] The VIP has been rescued, Counter-Terrorists win."); break; } } } } return Plugin_Continue; }
public Action:OnWeaponCanUse(client, weapon) { if(CurrentState != VIPState_Playing || client != CurrentVIP) { return Plugin_Continue; } new String:entityClassName[256]; GetEntityClassname(weapon, entityClassName, sizeof(entityClassName)); new String:VIPWeapon[256]; GetConVarString(CVarVIPWeapon, VIPWeapon, sizeof(VIPWeapon)); if(StrEqual(entityClassName, "weapon_knife", false) || StrEqual(entityClassName, VIPWeapon, false)) { return Plugin_Continue; } return Plugin_Handled; }
public Action:Command_JoinTeam(client, const String:command[], argc) { if(CurrentState != VIPState_Playing || client != CurrentVIP) { return Plugin_Continue; } PrintToChat(client, "%s", "[GO:VIP] You are not allowed to change teams while you are the VIP."); return Plugin_Handled; }
bool:IsValidPlayer(client) { if(!IsValidEntity(client) || !IsClientConnected(client) || !IsClientInGame(client)) { return false; } return true; }
GetRandomPlayerOnTeam(team, ignore = 0) { new teamClientCount = GetTeamClientCount(team); if(teamClientCount <= 0) { return 0; } new client; do { client = GetRandomInt(1, MaxClients); } while((teamClientCount > 1 && client == ignore) || !IsClientInGame(client) || GetClientTeam(client) != team); return client; }
stock RemoveMapObj() { decl maxent,i; decl String:Class[65]; maxent = GetMaxEntities(); for (i=0;i<=maxent;i++) { if(IsValidEdict(i) && IsValidEntity(i)) { GetEdictClassname(i, Class, sizeof(Class)); if(StrContains("func_bomb_target_hostage_entity_func_hostage_rescue",Class) != -1) { RemoveEdict(i); } } } }
StripWeapons(client) { new weaponID;
for(new x = 0; x < 20; x = (x + 4)) { weaponID = GetEntDataEnt2(client, MyWeaponsOffset + x); if(weaponID <= 0) { continue; } new String:weaponClassName[128]; GetEntityClassname(weaponID, weaponClassName, sizeof(weaponClassName)); if(StrEqual(weaponClassName, "weapon_knife", false)) { continue; }
RemovePlayerItem(client, weaponID); RemoveEdict(weaponID); } }
public TouchRescueZone(trigger, client) {
if(!IsValidPlayer(client)) { return; }
if(CurrentState != VIPState_Playing || client != CurrentVIP || RoundComplete) { return; } winner = 22; RoundComplete = true; CS_TerminateRound(6.0, CSRoundEnd_VIPEscaped); for (new i = 1; i <= MaxClients; i++) { if (IsClientInGame(i)) { EmitSoundToClient(i, "govip/vip_escaped.wav", _, _, _, _, 1.0, _, _, _, _, _, _); } } PrintCenterTextAll("The VIP Escaped!"); LastVIP = CurrentVIP;
CurrentVIP = 0;
PrintToChatAll("[GO:VIP] The VIP has been rescued, Counter-Terrorists win."); }
public FreezePlayer(client) { SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", 0.0); SetEntityRenderColor(client, 255, 0, 170, 174); ScreenFade(client, 0, 0, 0, 255, 2, OUT); }
public UnFreezePlayer(client) { SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", 1.0); SetEntityRenderColor(client, 255, 255, 255, 255); }
public ScreenFade(client, red, green, blue, alpha, delay, type) { new Handle:msg; new duration; duration = delay * 1000; msg = StartMessageOne("Fade", client); BfWriteShort(msg, 500); BfWriteShort(msg, duration); BfWriteShort(msg, type); BfWriteByte(msg, red); BfWriteByte(msg, green); BfWriteByte(msg, blue); BfWriteByte(msg, alpha); EndMessage(); }
public ConVarChanged_Restartgame(Handle:convar, const String:oldValue[], const String:newValue[]) { if (String:oldValue[0] == String:newValue[0]) { return; } else { t_incScore = 0; ct_incScore = 0; CTscore = 0; } }
Files are below. All sounds/models included. Change as you like. GL & HF!
If anyone needs help/walk-u-thru fixing the plugin for csgo and is able to test it ingame, contact me here: [email protected]
I don't own CS:GO nor CS:GO server, so I can't code and test.
Last edited by viksando; 02-02-2018 at 12:03.
|
|