Server Name:
TTT
Suggestion Title:
Suggestion for an improved player experience regarding prop possession - Giving the player a definitive choice.
How would it benefit the server:
By giving the player a choice to toggle incomming damage from possessed props, the player does not feel that the props have as much of an impact on them, and the outcome of the round.
Although the possessed props cannot directly kill the player. The props can still push around and block the player. But the player can rest assured the possessed prop will not be what kills them. - But, maybe, rather it will be from the impact of hitting the ground too hard, when they get launched off an egde, or into a hazard, by a possessed prop.
I know that you are working on logging possessed props that kill players, and enforcing the "You need to ask if it's ok first" thing.
I guess i'm just more of an authoritarian, and think that giving the player a choice, that restricts the possessed props killing them in the first place. Would be more of a definitive,
i want, or,
i don't want, kind of way to say whether it's ok or not, for the possessed props to kill the player.
Players can choose to turn it off/on, and the players that want to fly around as a prop can do that, without
accidentally killing someone that
wasn't ok with it.
I think this is the best of both worlds.
I guess i should tell you how this would work.
The player has an option to toggle on and off. That option is if they want to, or don't want to take damage from the possessed props that are flying around. Like the pointshop vapes/auras/web taunts are on and off options.
When a possessed prop flies into them, if the player has the possessed prop damage off, instead of dying on the spot, they at most get pushed out of the way, by the possessed prop.
Whether this push, also pushes them off the top of a building, or into a traitor trap... that will depend on the place and time.
On the server-side there will be a command to toggle all possessed props' collision on and off, if and when it should be needed.
YouTube video of an older demo version of this suggestion - contains a bit technical explaination.
I understand that you are only
that many developers, and that you have a whole process of doing things.
but, i offer you these code segments as my suggestion.
I don't know if there are security or integrity issues with that. I left at least one part of the code unfinished (server-side command thing). So whoever may use it, has to
fix it, if they want it to support something like ULX.
Spoiler below contains the LUA code.
player.lua:
At line 10 or after "
local pairs = pairs"
-- Start of code insert
local entityList = {}
local plyList = {}
if SERVER then
concommand.Add("ttt_spec_prop_toggle_com",
function(ply, cmd, args, argStr)
--Code but in server-privileged form(?)
if ply == NULL then --NULL entity if command was entered with the dedicated server console.
local convar = GetConVar("ttt_spec_prop_toggle")
local var = convar:GetInt()
local function CheckEntitiesToSetCollisionOff()
if not table.IsEmpty(entityList) then
for k, v in pairs(entityList) do
Entity( v ):SetCollisionGroup(COLLISION_GROUP_WORLD)
Entity( v ):DrawShadow(true) -- do you want the prop to cast a shadow?
end
entityList = {}
plyList = {}
end
end
if argStr == "0" or argStr == "1" then -- (Apply as 'set convar as arg' mode)
if argStr != var then -- Sender DID NOT try to set the variable to IT'S same value.
if argStr == "1" then
CheckEntitiesToSetCollisionOff()
end
convar:SetInt(argStr)
end
else -- Apply as 'toggle' mode - Disregard all args that might have been passed.
if var == 0 then -- Set to 1, and,
CheckEntitiesToSetCollisionOff()
convar:SetInt(1)
elseif var == 1 then -- Set to 0
convar:SetInt(0)
end
end
end
end, nil, "Toggle prop possession command. \n Additionally, you can add '0' or '1' as an argument which will be passed along, and set 'ttt_spec_prop_toggle' as that value.", "0")
--print("ttt_spec_prop_toggle_com init")
else return end
-- End of code insert
player.lua:
At line 367 or after "
if ply.propspec then"
-- Start of code insert
if SERVER then
if key == 4 then -- instead of also making an edit to propspec.lua. we can catch the player leaving the possessed prop here.
--print(ply:GetName(), "left the prop", CurTime())
for k, v in pairs(plyList) do
if ply:EntIndex() == v then
--print(v, k, Entity( v ), Entity( entityList[k] ))
Entity( entityList[k] ):SetNWInt( "spec_abandoned_time", CurTime() + 2 )
table.remove(plyList, k)
table.remove(entityList, k)
end
end
end
end
-- End of code insert
player.lua:
At line 499 or after "
PROPSPEC.Target(ply, tr.Entity)"
-- Start of code insert
if not SERVER then return end
local var = GetConVar("ttt_spec_prop_toggle"):GetInt()
if var == 0 then
tr.Entity:SetCollisionGroup(COLLISION_GROUP_NONE)
tr.Entity:DrawShadow(true)
local entID = tr.Entity:EntIndex()
if (not table.HasValue(entityList, entID)) then
table.insert(entityList, entID)
table.insert(plyList, ply:EntIndex())
end
elseif var == 1 then
tr.Entity:SetCollisionGroup(COLLISION_GROUP_WORLD)
tr.Entity:DrawShadow(true)
else
--print("The value of ttt_spec_prop_toggle was neither 1 or 0")
end
-- End of code insert
player.lua:
At line 981 or after "
end" of "if (ent:IsExplosive() or (ent:IsPlayer() and IsValid(att) and att:IsPlayer())) then"
-- Start of code insert
elseif ent:GetClass() == "prop_physics" or ent:GetClass() == "prop_physics_multiplayer" and dmginfo:GetInflictor():GetClass() == "weapon_ttt_push" then
if ent:GetNWInt("push_time", 0) < CurTime() then -- apply custom newton lancher attribute
ent:SetNWInt("push_time", CurTime() + 4) -- 4 sec where it will count as a kill - from "if t > owner_time and t > CurTime() - 4 then"
if GetConVar("ttt_spec_prop_toggle"):GetInt() == 1 and ent:GetCollisionGroup() == COLLISION_GROUP_WORLD then --it should not matter if the prop is possessed, and the first 'elseif' condition has already ensured its a prop.
--make and start timer that counts down until the possessed prop returns to no collision
local shouldOccur = true
local function SetCollisionAndTimer()
if shouldOccur then
ent:SetCollisionGroup(COLLISION_GROUP_NONE)
shouldOccur = false
timer.Simple( 4,
function()
if GetConVar("ttt_spec_prop_toggle"):GetInt() == 1 then
ent:SetCollisionGroup(COLLISION_GROUP_WORLD)
end
shouldOccur = true
end
)
end
end
SetCollisionAndTimer()
end
end
-- End of code insert
player.lua:
At line 1119 or after "
-- this is prop-based physics damage" in "if not dmginfo:IsDamageType(DMG_PHYSGUN) then"
-- Start of code insert
if tobool(Player(ent:UserID()):GetInfo( "ttt_spec_prop_user_toggle" )) and tobool(infl:GetNWInt("spec_owner", 0) or infl:GetNWInt("spec_abandoned_time", 0) > CurTime()) and tobool(not (infl:GetNWInt("push_time", 0) > CurTime())) then
dmginfo:ScaleDamage(0)
else
dmginfo:ScaleDamage(0.25)
end
-- End of code insert
-- Start of code override
--dmginfo:ScaleDamage(0.25)
-- End of code override
init.lua:
@line 113 or after "
CreateConVar("ttt_namechange_bantime", "10")"
-- Start of code insert
CreateConVar("ttt_spec_prop_toggle", "0", FCVAR_LUA_SERVER + FCVAR_NOTIFY + FCVAR_REPLICATED, "Toggle ability for spectators to posses props with collision", 0, 1)
--print("ttt_spec_prop_toggle init")
-- End of code insert
cl_init.lua:
At line 48 or after "
MsgN("TTT Client initializing...")"
-- Start of code insert
CreateClientConVar("ttt_spec_prop_user_toggle", "0", true, true, "Toggle user's stands on spectators dealing prop damage (DMG_CRUSH) to them. \n '0' = Will take damage; '1' = Will NOT take damage.", 0, 1)
--print("ttt_spec_prop_user_toggle_test init")
-- End of code insert
weapon_ttt_push.lua:
At line 124 or after "
ply.was_pushed = {att=owner, t=CurTime(), wep=self:GetClass()}"
-- Start of code insert
elseif SERVER and IsValid(ply) then
dmginfo:SetInflictor( Entity(self:EntIndex()) )
-- End of code insert
Potential Issues/Exploits:
The code has been tested on the "
vanilla" or "
otherwise unmodified" version of TTT.
The code has been tested for its function on local and peer-to-peer servers. I can tell you it works there.
But i don't know if 100% of it will work on the Zarp TTT server.
The part i left unfinished:
A spectator in control of an possessed prop, could launch the prop at another player, and then quickly 'leave' the prop before it hits the player to get around the whole "possessed prop damage" thing.
So i have set a 'timer' on the prop, then it will still count as possessed and not deal "possessed prop damage" to the player.
Entity( entityList[k] ):SetNWInt( "spec_abandoned_time", CurTime() + 2 )
This 'timer' is 2 seconds, and may be too short or too long time.
Additional notes:
This also assumes that you can posses props in the first place.
And that possessed prop have enough power force to fly around.