diff --git a/l4d2_ladder_editor.sp b/l4d2_ladder_editor.sp index f998721..7f4d4ae 100644 --- a/l4d2_ladder_editor.sp +++ b/l4d2_ladder_editor.sp @@ -1,18 +1,17 @@ #pragma semicolon 1 +#pragma newdecls required #include #include #include -#pragma newdecls required - #define MAX_STR_LEN 100 #define DEFAULT_STEP_SIZE 1.0 #define TEAM_INFECTED 3 #define HUD_DRAW_INTERVAL 0.5 static int selectedLadder[MAXPLAYERS + 1]; -static int bEditMode[MAXPLAYERS + 1]; +static bool bEditMode[MAXPLAYERS + 1]; static float stepSize[MAXPLAYERS + 1]; StringMap hLadders; bool in_attack[MAXPLAYERS + 1]; @@ -25,22 +24,30 @@ bool bHudHintShown[MAXPLAYERS + 1]; public Plugin myinfo = { name = "L4D2 Ladder Editor", author = "devilesk", - version = "0.5.0", + version = "0.5.0.1", description = "Clone and move special infected ladders.", url = "https://github.com/devilesk/rl4d2l-plugins" }; public void OnPluginStart() { - RegConsoleCmd("sm_edit", Command_Edit); - RegConsoleCmd("sm_step", Command_Step); - RegConsoleCmd("sm_select", Command_Select); - RegConsoleCmd("sm_clone", Command_Clone); - RegConsoleCmd("sm_move", Command_Move); - RegConsoleCmd("sm_nudge", Command_Nudge); - RegConsoleCmd("sm_rotate", Command_Rotate); - RegConsoleCmd("sm_kill", Command_Kill); - RegConsoleCmd("sm_info", Command_Info); - RegConsoleCmd("sm_togglehud", Command_ToggleHud); + /* + - While in edit mode, ladders you are aiming at can be selected using MOUSE1 and moved using MOUSE2 or WASD, USE, and RELOAD. + - TAB to toggle edit mode. SHIFT to rotate ladders in 90 degree increments. + */ + + RegConsoleCmd("sm_edit", Command_Edit, "Toggle edit mode on or off"); + RegConsoleCmd("sm_step", Command_Step, "sm_step - Number of units to move when moving ladders in edit mode."); + RegConsoleCmd("sm_select", Command_Select, "Select the ladder you are aiming at."); + RegConsoleCmd("sm_clone", Command_Clone, "Clone the selected ladder."); + RegConsoleCmd("sm_move", Command_Move, "sm_move - Move the selected ladder to the given coordinate on the map."); + RegConsoleCmd("sm_nudge", Command_Nudge, "sm_nudge - Move the selected ladder relative to its current position."); + RegConsoleCmd("sm_rotate", Command_Rotate, "sm_rotate - Rotate the selected ladder."); + RegConsoleCmd("sm_kill", Command_Kill, "Remove the selected ladder."); + RegConsoleCmd("sm_info", Command_Info, "Display info about the selected ladder entity."); + RegConsoleCmd("sm_togglehud", Command_ToggleHud, "Toggle selected ladder info HUD on or off."); + RegConsoleCmd("sm_team", Command_Team, "sm_team - Change team the ladder can used by"); + //RegConsoleCmd("sm_create", Command_Create, "Creates a ladder"); // TODO + HookEvent("player_team", PlayerTeam_Event); hLadders = new StringMap(); for (int i = 1; i <= MaxClients; i++) { @@ -56,6 +63,65 @@ public void OnPluginStart() { CreateTimer(HUD_DRAW_INTERVAL, HudDrawTimer, _, TIMER_REPEAT); } +public Action Command_Create(int client, int args) +{ + float pos[3]; + GetClientAbsOrigin(client, pos); + int entity = CreateEntityByName("func_simpleladder"); + if (entity == -1) + { + PrintToChat(client, "Failed to create ladder."); + return Plugin_Handled; + } + DispatchKeyValue(entity, "model", "*25"); // TODO. Replace by correct model + DispatchKeyValue(entity, "normal.z", "0.00"); + DispatchKeyValue(entity, "normal.y", "1.00"); + DispatchKeyValue(entity, "normal.x", "0.00"); + DispatchKeyValue(entity, "team", "0"); + DispatchKeyValue(entity, "angles", "0 0 0"); + DispatchKeyValueVector(entity, "origin", pos); + DispatchSpawn(entity); + + PrintToChat(client, "Ladder created. Index: %i", entity); + return Plugin_Handled; +} + +public Action Command_Team(int client, int args) +{ + if (args < 1) + { + PrintToChat(client, "Using: sm_team - 0: any, 1 - survivors, 2 - infected"); + return Plugin_Handled; + } + char buf[4]; + GetCmdArg(1, buf, sizeof buf); + int newteam = StringToInt(buf); + + char classname[MAX_STR_LEN]; + int entity = GetClientAimTarget(client, false); + if (IsValidEntity(entity)) { + GetEntityClassname(entity, classname, MAX_STR_LEN); + if (StrEqual(classname, "func_simpleladder", false)) { + int team; + char modelname[128]; + float origin[3], position[3], normal[3], angles[3]; + GetLadderEntityInfo(entity, modelname, sizeof(modelname), origin, position, normal, angles, team); + SetEntProp(entity, Prop_Send, "m_iTeamNum", newteam); + PrintToChat(client, "Ladder entity %i, %s at (%.2f,%.2f,%.2f). Team changed: %i => %i", entity, modelname, position[0], position[1], position[2], team, newteam); + + } + else { + selectedLadder[client] = -1; + PrintToChat(client, "Not looking at a ladder. Entity %i, classname: %s", entity, classname); + } + } + else { + selectedLadder[client] = -1; + PrintToChat(client, "Looking at invalid entity %i", entity); + } + return Plugin_Handled; +} + public void OnMapStart() { for (int i = 1; i <= MaxClients; i++) { selectedLadder[i] = -1; @@ -69,7 +135,7 @@ public void OnMapStart() { } hLadders.Clear(); } - + public void OnClientAuthorized(int client, const char[] auth) { bHudHintShown[client] = false; @@ -86,7 +152,7 @@ public void OnClientDisconnect_Post(int client) stepSize[client] = DEFAULT_STEP_SIZE; } -stock void SetClientFrozen(int client, int freeze) +stock void SetClientFrozen(int client, bool freeze) { SetEntityMoveType(client, freeze ? MOVETYPE_NONE : MOVETYPE_WALK); } @@ -95,19 +161,18 @@ public Action Command_ToggleHud(int client, int args) { bHudActive[client] = !bHudActive[client]; CPrintToChat(client, "<{olive}HUD{default}> Ladder Editor HUD is now %s.", (bHudActive[client] ? "{blue}on{default}" : "{red}off{default}")); + return Plugin_Handled; } public Action HudDrawTimer(Handle hTimer) { - - for (int i = 1; i <= MaxClients; i++) { if (!bHudActive[i] || IsFakeClient(i)) continue; - Handle hud = CreatePanel(); + Panel hud = new Panel(); FillHudInfo(i, hud); - SendPanelToClient(hud, i, DummyHudHandler, 3); + hud.Send(i, DummyHudHandler, 3); delete hud; if (!bHudHintShown[i]) { @@ -115,50 +180,50 @@ public Action HudDrawTimer(Handle hTimer) CPrintToChat(i, "<{olive}HUD{default}> Type {green}!togglehud{default} into chat to toggle the {blue}Ladder Editor HUD{default}."); } } + return Plugin_Continue; } -public int DummyHudHandler(Handle hMenu, MenuAction action, int param1, int param2) {} +public int DummyHudHandler(Menu hMenu, MenuAction action, int param1, int param2) { return 0; } -public void FillHudInfo(int client, Handle hHud) +public void FillHudInfo(int client, Panel hHud) { - DrawPanelText(hHud, "Ladder Editor HUD"); - DrawPanelText(hHud, " "); + hHud.DrawText("Ladder Editor HUD"); + hHud.DrawText(" "); char buffer[512]; Format(buffer, sizeof(buffer), "Edit mode: %s", (bEditMode[client] ? "on" : "off")); - DrawPanelText(hHud, buffer); - DrawPanelText(hHud, " "); + hHud.DrawText(buffer); + hHud.DrawText(" "); int entity = selectedLadder[client]; if (!IsValidEntity(entity)) { Format(buffer, sizeof(buffer), "No ladder selected."); - DrawPanelText(hHud, buffer); + hHud.DrawText(buffer); return; } char modelname[128]; - float origin[3]; - float position[3]; - float normal[3]; - float angles[3]; - GetLadderEntityInfo(entity, modelname, sizeof(modelname), origin, position, normal, angles); + float origin[3], position[3], normal[3], angles[3]; + int team; + GetLadderEntityInfo(entity, modelname, sizeof(modelname), origin, position, normal, angles, team); Format(buffer, sizeof(buffer), "Entity: %i", entity); - DrawPanelText(hHud, buffer); + hHud.DrawText(buffer); Format(buffer, sizeof(buffer), "Model Name: %s", modelname); - DrawPanelText(hHud, buffer); + hHud.DrawText(buffer); Format(buffer, sizeof(buffer), "Position: %.2f, %.2f, %.2f", position[0], position[1], position[2]); - DrawPanelText(hHud, buffer); + hHud.DrawText(buffer); Format(buffer, sizeof(buffer), "Origin: %.2f, %.2f, %.2f", origin[0], origin[1], origin[2]); - DrawPanelText(hHud, buffer); + hHud.DrawText(buffer); Format(buffer, sizeof(buffer), "Normal: %.2f, %.2f, %.2f", normal[0], normal[1], normal[2]); - DrawPanelText(hHud, buffer); + hHud.DrawText(buffer); Format(buffer, sizeof(buffer), "Angles: %.2f, %.2f, %.2f", angles[0], angles[1], angles[2]); - DrawPanelText(hHud, buffer); + hHud.DrawText(buffer); + Format(buffer, sizeof(buffer), "Team: %i", team); + hHud.DrawText(buffer); } public bool GetEndPosition(int client, float end[3]) { - float start[3]; - float angle[3]; + float start[3], angle[3]; GetClientEyePosition(client, start); GetClientEyeAngles(client, angle); TR_TraceRayFilter(start, angle, MASK_SOLID, RayType_Infinite, TraceEntityFilterPlayer, client); @@ -170,7 +235,7 @@ public bool GetEndPosition(int client, float end[3]) return false; } -public bool TraceEntityFilterPlayer(int entity, int contentsMask, any data) +public bool TraceEntityFilterPlayer(int entity, int contentsMask, int data) { return entity > MaxClients; } @@ -259,11 +324,10 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3 return Plugin_Continue; } -public Action PlayerTeam_Event(Handle event, const char[] name, bool dontBroadcast) +public void PlayerTeam_Event(Event event, const char[] name, bool dontBroadcast) { - int client = GetClientOfUserId(GetEventInt(event, "userid")); - int team = GetEventInt(event, "team"); - if (team != TEAM_INFECTED && bEditMode[client]) { + int client = GetClientOfUserId(event.GetInt("userid")); + if (bEditMode[client]) { bEditMode[client] = false; PrintToChat(client, "Exiting edit mode."); } @@ -290,10 +354,12 @@ public Action Command_Step(int client, int args) public Action Command_Edit(int client, int args) { + /* if (GetClientTeam(client) != TEAM_INFECTED) { PrintToChat(client, "Must be on infected team to enter edit mode."); return Plugin_Handled; } + */ if (bEditMode[client]) { bEditMode[client] = false; SetClientFrozen(client, false); @@ -317,8 +383,7 @@ public Action Command_Kill(int client, int args) float normal[3]; float origin[3]; float position[3]; - float mins[3]; - float maxs[3]; + float mins[3], maxs[3]; GetEntPropVector(entity, Prop_Send, "m_climbableNormal", normal); GetEntPropVector(entity, Prop_Send, "m_vecOrigin", origin); GetEntPropVector(entity,Prop_Send,"m_vecMins",mins); @@ -330,7 +395,7 @@ public Action Command_Kill(int client, int args) selectedLadder[client] = -1; char key[8]; IntToString(entity, key, 8); - RemoveFromTrie(hLadders, key); + hLadders.Remove(key); PrintToChat(client, "Killed ladder entity %i, %s at (%.2f,%.2f,%.2f). origin: (%.2f,%.2f,%.2f). normal: (%.2f,%.2f,%.2f)", entity, modelname, position[0], position[1], position[2], origin[0], origin[1], origin[2], normal[0], normal[1], normal[2]); } else { @@ -339,15 +404,16 @@ public Action Command_Kill(int client, int args) return Plugin_Handled; } -public void GetLadderEntityInfo(int entity, char[] modelname, int modelnamelen, float origin[3], float position[3], float normal[3], float angles[3]) { - float mins[3]; - float maxs[3]; +public void GetLadderEntityInfo(int entity, char[] modelname, int modelnamelen, float origin[3], float position[3], float normal[3], float angles[3], int &team) { + float mins[3], maxs[3]; GetEntPropString(entity, Prop_Data, "m_ModelName", modelname, modelnamelen); GetEntPropVector(entity, Prop_Send, "m_vecOrigin", origin); GetEntPropVector(entity, Prop_Send, "m_vecMins", mins); GetEntPropVector(entity, Prop_Send, "m_vecMaxs", maxs); GetEntPropVector(entity, Prop_Send, "m_climbableNormal", normal); GetEntPropVector(entity, Prop_Send, "m_angRotation", angles); + team = GetEntProp(entity, Prop_Send, "m_iTeamNum"); + Math_RotateVector(mins, angles, mins); Math_RotateVector(maxs, angles, maxs); position[0] = origin[0] + (mins[0] + maxs[0]) * 0.5; @@ -358,17 +424,19 @@ public void GetLadderEntityInfo(int entity, char[] modelname, int modelnamelen, public Action Command_Info(int client, int args) { char classname[MAX_STR_LEN]; + int team; int entity = GetClientAimTarget(client, false); if (IsValidEntity(entity)) { GetEntityClassname(entity, classname, MAX_STR_LEN); if (StrEqual(classname, "func_simpleladder", false)) { char modelname[128]; - float origin[3]; - float position[3]; - float normal[3]; - float angles[3]; - GetLadderEntityInfo(entity, modelname, sizeof(modelname), origin, position, normal, angles); - + float origin[3], position[3], normal[3], angles[3]; + GetLadderEntityInfo(entity, modelname, sizeof(modelname), origin, position, normal, angles, team); + + float mins[3], maxs[3]; + GetEntPropVector(entity, Prop_Send, "m_vecMins", mins); + GetEntPropVector(entity, Prop_Send, "m_vecMaxs", maxs); + PrintToChat(client, "Ladder entity %i, %s at (%.2f,%.2f,%.2f). origin: (%.2f,%.2f,%.2f). normal: (%.2f,%.2f,%.2f). angles: (%.2f,%.2f,%.2f)", entity, modelname, position[0], position[1], position[2], origin[0], origin[1], origin[2], normal[0], normal[1], normal[2], angles[0], angles[1], angles[2]); PrintToConsole(client, "add:"); @@ -377,11 +445,13 @@ public Action Command_Info(int client, int args) PrintToConsole(client, " \"normal.z\" \"%.2f\"", normal[2]); PrintToConsole(client, " \"normal.y\" \"%.2f\"", normal[1]); PrintToConsole(client, " \"normal.x\" \"%.2f\"", normal[0]); - PrintToConsole(client, " \"team\" \"2\""); + PrintToConsole(client, " \"team\" \"%i\"", team); PrintToConsole(client, " \"classname\" \"func_simpleladder\""); PrintToConsole(client, " \"origin\" \"%.2f %.2f %.2f\"", origin[0], origin[1], origin[2]); PrintToConsole(client, " \"angles\" \"%.2f %.2f %.2f\"", angles[0], angles[1], angles[2]); PrintToConsole(client, "}"); + PrintToConsole(client, "// mins: \"%.2f %.2f %.2f\"", mins[0], mins[1], mins[2]); + PrintToConsole(client, "// maxs: \"%.2f %.2f %.2f\"", maxs[0], maxs[1], maxs[2]); } else { PrintToChat(client, "Not looking at a ladder. Entity %i, classname: %s", entity, classname); @@ -398,11 +468,9 @@ public void RotateStep(int client) int entity = selectedLadder[client]; if (IsValidEntity(entity)) { char modelname[128]; - float origin[3]; - float position[3]; - float normal[3]; - float angles[3]; - GetLadderEntityInfo(entity, modelname, sizeof(modelname), origin, position, normal, angles); + float origin[3], position[3], normal[3], angles[3]; + int team; + GetLadderEntityInfo(entity, modelname, sizeof(modelname), origin, position, normal, angles, team); Rotate(client, 0.0, angles[1] + 90, 0.0, true); } else { @@ -443,21 +511,15 @@ public void Rotate(int client, float x, float y, float z, bool bPrint) PrintToChat(client, "Original ladder not found."); return; } - + int team; char modelname[128]; - float sourceOrigin[3]; - float sourcePos[3]; - float sourceNormal[3]; - float sourceAngles[3]; - GetLadderEntityInfo(sourceEnt, modelname, sizeof(modelname), sourceOrigin, sourcePos, sourceNormal, sourceAngles); + float sourceOrigin[3], sourcePos[3], sourceNormal[3], sourceAngles[3]; + GetLadderEntityInfo(sourceEnt, modelname, sizeof(modelname), sourceOrigin, sourcePos, sourceNormal, sourceAngles, team); if (bPrint) PrintToChat(client, "Original ladder entity %i at (%.2f,%.2f,%.2f)", sourceEnt, sourcePos[0], sourcePos[1], sourcePos[2]); - float origin[3]; - float position[3]; - float normal[3]; - float angles[3]; - GetLadderEntityInfo(entity, modelname, sizeof(modelname), origin, position, normal, angles); + float origin[3], position[3], normal[3], angles[3]; + GetLadderEntityInfo(entity, modelname, sizeof(modelname), origin, position, normal, angles, team); angles[0] = x; angles[1] = y; @@ -498,11 +560,9 @@ public void Move(int client, float x, float y, float z, bool bPrint) } char modelname[128]; - float origin[3]; - float sourcePos[3]; - float normal[3]; - float angles[3]; - GetLadderEntityInfo(sourceEnt, modelname, sizeof(modelname), origin, sourcePos, normal, angles); + float origin[3], sourcePos[3], normal[3], angles[3]; + int team; + GetLadderEntityInfo(sourceEnt, modelname, sizeof(modelname), origin, sourcePos, normal, angles, team); if (bPrint) PrintToChat(client, "Original ladder entity %i at (%.2f,%.2f,%.2f)", sourceEnt, sourcePos[0], sourcePos[1], sourcePos[2]); @@ -527,9 +587,7 @@ public Action Command_Rotate(int client, int args) PrintToChat(client, "[SM] Usage: sm_rotate "); return Plugin_Handled; } - char x[8]; - char y[8]; - char z[8]; + char x[8], y[8], z[8]; GetCmdArg(1, x, sizeof(x)); GetCmdArg(2, y, sizeof(y)); GetCmdArg(3, z, sizeof(z)); @@ -577,11 +635,9 @@ public Action Command_Clone(int client, int args) return Plugin_Handled; } char modelname[128]; - float origin[3]; - float position[3]; - float normal[3]; - float angles[3]; - GetLadderEntityInfo(sourceEnt, modelname, sizeof(modelname), origin, position, normal, angles); + float origin[3], position[3], normal[3], angles[3]; + int team; + GetLadderEntityInfo(sourceEnt, modelname, sizeof(modelname), origin, position, normal, angles, team); PrecacheModel(modelname, true); int entity = CreateEntityByName("func_simpleladder"); if (entity == -1) @@ -590,6 +646,8 @@ public Action Command_Clone(int client, int args) return Plugin_Handled; } char buf[32]; + char sTeam[32]; + IntToString(team, sTeam, sizeof sTeam); DispatchKeyValue(entity, "model", modelname); Format(buf, sizeof(buf), "%.6f", normal[2]); DispatchKeyValue(entity, "normal.z", buf); @@ -597,15 +655,16 @@ public Action Command_Clone(int client, int args) DispatchKeyValue(entity, "normal.y", buf); Format(buf, sizeof(buf), "%.6f", normal[0]); DispatchKeyValue(entity, "normal.x", buf); - DispatchKeyValue(entity, "team", "2"); - DispatchKeyValue(entity, "origin", "50 0 0"); + DispatchKeyValue(entity, "team", sTeam); + DispatchKeyValue(entity, "origin", "0 0 0"); DispatchSpawn(entity); + selectedLadder[client] = entity; char key[8]; IntToString(entity, key, 8); - SetTrieValue(hLadders, key, sourceEnt, true); - PrintToChat(client, "Cloned ladder entity %i. New entity %i", sourceEnt, entity); + hLadders.SetValue(key, sourceEnt, true); + PrintToChat(client, "Cloned ladder entity %i. int entity %i", sourceEnt, entity); } else { PrintToChat(client, "No ladder selected."); @@ -621,14 +680,11 @@ public Action Command_Select(int client, int args) GetEntityClassname(entity, classname, MAX_STR_LEN); if (StrEqual(classname, "func_simpleladder", false)) { selectedLadder[client] = entity; - + int team; char modelname[128]; - float origin[3]; - float position[3]; - float normal[3]; - float angles[3]; - GetLadderEntityInfo(entity, modelname, sizeof(modelname), origin, position, normal, angles); - PrintToChat(client, "Selected ladder entity %i, %s at (%.2f,%.2f,%.2f). origin: (%.2f,%.2f,%.2f). normal: (%.2f,%.2f,%.2f)", entity, modelname, position[0], position[1], position[2], origin[0], origin[1], origin[2], normal[0], normal[1], normal[2]); + float origin[3], position[3], normal[3], angles[3]; + GetLadderEntityInfo(entity, modelname, sizeof(modelname), origin, position, normal, angles, team); + PrintToChat(client, "Selected ladder entity %i, %s at (%.2f,%.2f,%.2f). origin: (%.2f,%.2f,%.2f). normal: (%.2f,%.2f,%.2f). Team: %i", entity, modelname, position[0], position[1], position[2], origin[0], origin[1], origin[2], normal[0], normal[1], normal[2], team); } else { selectedLadder[client] = -1; @@ -652,9 +708,9 @@ public Action Command_Select(int client, int args) * angles[1] = 0.0; * angles[2] = playerEyeAngles[1]; * - * @param vec Vector to rotate. - * @param angles How to rotate the vector. - * @param result Output vector. + * @param vec Vector to rotate. + * @param angles How to rotate the vector. + * @param result Output vector. * @noreturn */ stock void Math_RotateVector(const float vec[3], const float angles[3], float result[3]) @@ -703,4 +759,4 @@ stock void Math_RotateVector(const float vec[3], const float angles[3], float re result[0] = x; result[1] = y; result[2] = z; -} \ No newline at end of file +}